Files
JoyD/Web/Vue/CubeLib
2026-02-02 14:11:58 +08:00
..
2026-01-30 15:38:48 +08:00
2026-02-02 14:11:58 +08:00
2026-02-02 13:46:36 +08:00
2026-02-02 13:46:36 +08:00
2026-02-02 14:11:58 +08:00
2026-02-02 13:46:36 +08:00

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, bottom
  • initialSize: 初始尺寸
  • 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 了解版本更新历史。