JoyD Vue3 CubeLib 组件库
简介
JoyD Vue3 CubeLib 是一个基于 Vue 3 开发的组件库,提供了一系列可复用的 UI 组件,旨在简化 Web 应用程序的开发流程。
特性
- 基于 Vue 3 构建
- TypeScript 支持
- 模块化设计
- 易于定制和扩展
- 丰富的组件库
安装
npm install joyd.web.vue.cubelib
# 或者
yarn add joyd.web.vue.cubelib
使用
全局注册
import { createApp } from 'vue'
import App from './App.vue'
import CubeLib from 'joyd.web.vue.cubelib'
const app = createApp(App)
app.use(CubeLib)
app.mount('#app')
按需导入
import { CubeSplitter } from 'joyd.web.vue.cubelib'
// 在组件中使用
export default {
components: {
CubeSplitter
}
}
组件文档
CubeSplitter
可调整大小的分隔条组件,用于在布局中创建可调整大小的面板。
Props
direction: 分隔条方向,可选值:vertical(垂直),horizontal(水平)position: 分隔条位置,可选值:left,right,top,bottominitialSize: 初始尺寸minSize: 最小尺寸maxSize: 最大尺寸
Events
resize: 调整大小时触发resizeEnd: 调整大小结束时触发collapse: 折叠面板时触发expand: 展开面板时触发
使用示例
<template>
<div class="container">
<div class="left-panel" :style="{ width: leftPanelWidth + 'px' }"></div>
<CubeSplitter
direction="vertical"
position="left"
:min-size="50"
:max-size="500"
:initial-size="200"
@resize="onLeftResize"
@resize-end="onLeftResizeEnd"
@collapse="onLeftCollapse"
@expand="onLeftExpand"
/>
<div class="middle-panel"></div>
<CubeSplitter
direction="vertical"
position="right"
:min-size="0"
:max-size="500"
:initial-size="200"
@resize="onRightResize"
@resize-end="onRightResizeEnd"
@collapse="onRightCollapse"
@expand="onRightExpand"
/>
<div class="right-panel" :style="{ width: rightPanelWidth + 'px' }"></div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
const leftPanelWidth = ref(200)
const rightPanelWidth = ref(200)
// 从 localStorage 加载保存的尺寸
onMounted(() => {
const savedLeftWidth = localStorage.getItem('leftPanelWidth')
const savedRightWidth = localStorage.getItem('rightPanelWidth')
if (savedLeftWidth) {
leftPanelWidth.value = parseInt(savedLeftWidth)
}
if (savedRightWidth) {
rightPanelWidth.value = parseInt(savedRightWidth)
}
})
// 左侧分隔条调整
const onLeftResize = (newWidth) => {
leftPanelWidth.value = newWidth
}
const onLeftResizeEnd = (finalWidth) => {
// 只保存正常尺寸,不保存折叠状态
if (finalWidth > 50) {
localStorage.setItem('leftPanelWidth', finalWidth.toString())
}
}
const onLeftCollapse = (newSize) => {
leftPanelWidth.value = newSize
}
const onLeftExpand = (newSize) => {
leftPanelWidth.value = newSize
}
// 右侧分隔条调整
const onRightResize = (newWidth) => {
rightPanelWidth.value = newWidth
}
const onRightResizeEnd = (finalWidth) => {
// 只保存正常尺寸,不保存折叠状态
if (finalWidth > 0) {
localStorage.setItem('rightPanelWidth', finalWidth.toString())
}
}
const onRightCollapse = (newSize) => {
rightPanelWidth.value = newSize
}
const onRightExpand = (newSize) => {
rightPanelWidth.value = newSize
}
</script>
<style scoped>
.container {
display: flex;
width: 100%;
height: 100vh;
overflow: hidden;
}
.left-panel {
background-color: #f0f0f0;
min-width: 50px;
}
.middle-panel {
flex: 1;
background-color: #ffffff;
}
.right-panel {
background-color: #f0f0f0;
min-width: 0;
border-left: 1px solid #e0e0e0;
}
</style>
CSS 变量
CubeSplitter 组件支持通过 CSS 变量进行定制:
:root {
--cube-splitter-color: #e0e0e0;
--cube-splitter-hover-color: #667eea;
--cube-splitter-active-color: #5568d3;
--cube-splitter-handle-color: #fff;
--cube-splitter-handle-shadow: 0 0 4px rgba(0, 0, 0, 0.2);
--cube-splitter-collapsing-color: #667eea;
--cube-splitter-collapsing-shadow: 0 0 10px rgba(102, 126, 234, 0.5);
--cube-splitter-transition-speed: 0.3s;
}
CubeWebSocket
一个功能完善的 WebSocket 组件,支持自动连接、重连、消息队列、心跳机制等功能。
Props
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| wsUrl | WebSocket 服务器地址 | String | '' |
| autoConnect | 是否自动连接 | Boolean | true |
| reconnect | 是否自动重连 | Boolean | true |
| maxReconnectDelay | 最大重连延迟(毫秒) | Number | 30000 |
| debugMode | 是否开启调试模式 | Boolean | false |
| heartbeatInterval | 心跳间隔(毫秒) | Number | 30000 |
| connectTimeout | 连接超时(毫秒) | Number | 10000 |
| maxQueueSize | 消息队列最大长度 | Number | 100 |
Events
| 事件名 | 说明 | 参数 |
|---|---|---|
| connected | 连接成功 | - |
| disconnected | 连接断开 | (code, reason) |
| error | 连接错误 | error |
| message | 收到消息 | message |
| status-changed | 状态变化 | status |
| connecting | 开始连接 | - |
| reconnecting | 开始重连 | - |
| message-sent | 消息已发送 | message |
| message-queued | 消息已加入队列 | message |
| message-failed | 消息发送失败 | { message, reason, error? } |
Methods
| 方法名 | 说明 | 参数 | 返回值 |
|---|---|---|---|
| connect | 连接 WebSocket | - | void |
| disconnect | 断开连接 | - | void |
| send | 发送消息 | (type, data) | void |
| reconnect | 手动触发重连 | - | void |
| getStatus | 获取当前状态 | - | string |
| isConnected | 是否已连接 | - | boolean |
| getQueueSize | 获取队列长度 | - | number |
使用示例
<template>
<div>
<div>状态: {{ status }}</div>
<div>消息数量: {{ messages.length }}</div>
<CubeWebSocket
ws-url="ws://localhost:8086/ws"
:auto-connect="true"
:reconnect="true"
:debug-mode="true"
@connected="handleConnected"
@disconnected="handleDisconnected"
@message="handleMessage"
@status-changed="handleStatusChanged"
/>
</div>
</template>
<script setup>
import { ref } from 'vue'
import CubeWebSocket from 'joyd.web.vue.cubelib'
const status = ref('disconnected')
const messages = ref([])
const handleConnected = () => {
console.log('WebSocket 已连接')
status.value = 'connected'
}
const handleDisconnected = (code, reason) => {
console.log('WebSocket 已断开:', code, reason)
status.value = 'disconnected'
}
const handleMessage = (message) => {
console.log('收到消息:', message)
messages.value.push(message)
}
const handleStatusChanged = (newStatus) => {
console.log('状态变化:', newStatus)
status.value = newStatus
}
</script>
详细文档请查看 CubeWebSocket.md
示例代码
CubeTreeView
树形视图组件,用于展示层级数据结构,支持展开/折叠、键盘导航、自定义样式等功能。
Props
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| data | 树形数据数组 | Array | [] |
| selectedId | 当前选中的节点ID | String | '' |
| config | 组件配置对象 | Object | 见下方配置说明 |
| iconMap | 自定义图标映射 | Object | - |
Config 配置对象
| 配置项 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| defaultExpandAll | 是否默认展开所有节点 | Boolean | false |
| showExpandIcon | 是否显示展开/折叠图标 | Boolean | true |
| indentSize | 缩进大小(像素) | Number | 16 |
| expandable | 是否允许展开/折叠 | Boolean | true |
| iconType | 图标类型:'custom'、'file'、'heading' | String | 'custom' |
| showLevel | 是否显示层级前缀 | Boolean | false |
| levelPrefix | 层级前缀文本 | String | 'H' |
| levelKey | 层级字段名 | String | 'level' |
| autoExpand | 选中节点时是否自动展开路径 | Boolean | false |
| highlightPath | 是否高亮选中节点的路径 | Boolean | false |
Events
| 事件名 | 说明 | 参数 |
|---|---|---|
| node-click | 节点被点击 | item |
| toggle-expand | 节点展开/折叠状态变化 | itemId |
Methods
| 方法名 | 说明 | 参数 | 返回值 |
|---|---|---|---|
| expandAll | 展开所有节点 | - | void |
| collapseAll | 折叠所有节点 | - | void |
| expandNode | 展开指定节点 | id | void |
| collapseNode | 折叠指定节点 | id | void |
| toggleNode | 切换节点展开/折叠状态 | id | void |
| expandPath | 展开到指定节点的路径 | id | void |
| collapsePath | 折叠到指定节点的路径 | id | void |
| getNodeById | 根据ID获取节点 | id | Object |
| getSelectedNode | 获取当前选中的节点 | - | Object |
| selectNode | 选中指定节点 | id | void |
Slots
| 插槽名 | 说明 | 作用域参数 |
|---|---|---|
| icon | 自定义节点图标 | { item } |
| title | 自定义节点标题 | { item } |
| prefix | 自定义节点前缀 | { item } |
| suffix | 自定义节点后缀 | { item } |
使用示例
<template>
<div class="tree-container">
<CubeTreeView
ref="treeViewRef"
:data="treeData"
:selected-id="selectedId"
:config="treeConfig"
@node-click="handleNodeClick"
@toggle-expand="handleToggleExpand"
>
<template #icon="{ item }">
<span class="custom-icon">{{ item.icon }}</span>
</template>
<template #title="{ item }">
<span class="custom-title">{{ item.title }}</span>
</template>
</CubeTreeView>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { CubeTreeView } from 'joyd.web.vue.cubelib'
const treeViewRef = ref(null)
const selectedId = ref('')
const treeData = ref([
{
id: '1',
title: '根节点1',
level: 1,
children: [
{
id: '1-1',
title: '子节点1-1',
level: 2,
children: [
{ id: '1-1-1', title: '叶子节点1-1-1', level: 3 },
{ id: '1-1-2', title: '叶子节点1-1-2', level: 3 }
]
},
{
id: '1-2',
title: '子节点1-2',
level: 2,
children: [
{ id: '1-2-1', title: '叶子节点1-2-1', level: 3 }
]
}
]
},
{
id: '2',
title: '根节点2',
level: 1,
children: [
{ id: '2-1', title: '子节点2-1', level: 2 }
]
}
])
const treeConfig = {
defaultExpandAll: false,
showExpandIcon: true,
indentSize: 16,
expandable: true,
iconType: 'custom',
showLevel: false,
autoExpand: true,
highlightPath: true
}
const handleNodeClick = (item) => {
console.log('节点被点击:', item)
selectedId.value = item.id
}
const handleToggleExpand = (itemId) => {
console.log('节点展开/折叠:', itemId)
}
</script>
<style scoped>
.tree-container {
width: 300px;
padding: 16px;
border: 1px solid #e0e0e0;
border-radius: 4px;
}
.custom-icon {
margin-right: 8px;
font-size: 16px;
}
.custom-title {
font-size: 14px;
}
</style>
键盘导航
CubeTreeView 支持以下键盘操作:
↑- 向上移动选择↓- 向下移动选择←- 折叠当前节点或选择父节点→- 展开当前节点或选择第一个子节点Enter/Space- 触发节点点击事件
CSS 变量
CubeTreeView 组件支持通过 CSS 变量进行定制:
:root {
--cube-tree-item-hover-bg: rgba(0, 0, 0, 0.05);
--cube-tree-item-selected-bg: #1890ff;
--cube-tree-item-selected-color: #ffffff;
--cube-tree-item-path-bg: rgba(24, 144, 255, 0.1);
--cube-tree-item-icon-color: rgba(0, 0, 0, 0.45);
--cube-tree-item-level-color: rgba(0, 0, 0, 0.45);
--cube-tree-item-title-color: inherit;
}
常见问题解答
Q: 如何保存分隔条的位置?
A: 可以使用 @resize-end 事件来保存最终的尺寸到 localStorage 或其他存储中,然后在组件挂载时从存储中加载。
Q: 如何在最小尺寸和当前尺寸之间切换?
A: 单击分隔条的句柄即可在最小尺寸和当前尺寸之间切换。
Q: 为什么右侧分隔条的拖拽方向与左侧不同?
A: CubeSplitter 组件统一了拖拽方向逻辑:向左/上拖动减小尺寸,向右/下拖动增大尺寸,无论分隔条位置是左还是右。
贡献
我们欢迎社区贡献!请阅读 贡献指南 了解如何参与。
许可证
MIT License
联系我们
版本历史
请查看 CHANGELOG.md 了解版本更新历史。