Private
Public Access
1
0
Files
u-desk/docs/04-功能迭代/GO-DESK-2.数据库客户端/核对报告/组件拆分方案.md

6.3 KiB
Raw Blame History

数据库客户端组件拆分方案

组件架构设计

组件拆分

index.vue 拆分为以下组件:

  1. ConnectionTree.vue - 左侧连接树形列表
  2. SqlEditor.vue - SQL编辑器区域
  3. ResultPanel.vue - 结果展示区域
  4. index.vue - 主组件(布局和状态管理)

组件职责划分

ConnectionTree.vue

  • 职责:连接列表管理、树形结构展示、数据库/表展开
  • 状态connections, treeData, loading, loadingNodes
  • 方法loadConnections, loadDatabases, loadTables
  • 事件
    • connection-select: 连接被选中
    • connection-edit: 编辑连接
    • connection-delete: 删除连接
    • connection-refresh: 需要刷新连接列表
    • table-select: 表被选中用于生成SQL
    • new-connection: 新建连接

SqlEditor.vue

  • 职责SQL编辑器、标签页管理、工具栏
  • Props
    • currentConnection: 当前选中的连接对象
  • 状态tabs, activeTab, editorView
  • 方法initEditor, handleAddTab, handleDeleteTab, handleExecute, handleExecuteSelected, handleFormat
  • 事件
    • execute: 执行SQL完整内容
    • execute-selected: 执行选中的SQL
    • format: 格式化SQL
    • sql-insert: 插入SQL到编辑器由表选择触发
    • tab-change: 标签页切换
    • sql-change: SQL内容变化

ResultPanel.vue

  • 职责结果展示表格、JSON、消息
  • Props
    • loading: 加载状态
    • error: 错误信息
    • data: 结果数据
    • mode: 展示模式table/json
    • stats: 执行统计信息
    • messages: 消息列表
  • 状态resultTab
  • 方法formatJSON
  • 事件:无(纯展示组件)

index.vue主组件

  • 职责
    • 布局管理(左侧、右侧、底部)
    • 状态协调(当前连接、执行结果)
    • 组件通信桥梁
    • 连接表单管理

组件通信方式

1. Props 向下传递

  • currentConnection → SqlEditor
  • loading, error, data, mode, stats, messages → ResultPanel

2. Events 向上传递

  • ConnectionTree 的事件 → index.vue 处理
  • SqlEditor 的事件 → index.vue 处理

3. 数据流向

ConnectionTree
  └─ connection-select ──→ index.vue ──→ SqlEditor (currentConnection prop)
                                    └─→ ResultPanel (clear data)

SqlEditor
  └─ execute ──→ index.vue ──→ ExecuteSQL API ──→ ResultPanel (result props)

ConnectionTree
  └─ table-select ──→ index.vue ──→ SqlEditor (sql-insert event)

状态管理

主组件 (index.vue) 管理的状态:

  • currentConnection: 当前选中的连接(需要传递给 SqlEditor
  • resultLoading, resultError, resultData, resultMode, resultStats: 执行结果(需要传递给 ResultPanel
  • messages: 消息列表(需要传递给 ResultPanel
  • showConnectionForm, editingConnectionId: 连接表单状态

子组件自己管理的状态:

  • ConnectionTree: connections, treeData, loading, loadingNodes
  • SqlEditor: tabs, activeTab, editorView
  • ResultPanel: resultTab

优势

  1. 职责清晰:每个组件只关注自己的功能
  2. 可维护性强:修改某个功能只需修改对应组件
  3. 可复用性ResultPanel 可以在其他地方复用
  4. 测试友好:每个组件可以独立测试
  5. 性能优化:可以针对单个组件进行优化

后续扩展

如果功能继续增加,可以考虑:

  1. 引入 Pinia/Vuex 进行全局状态管理
  2. 使用 provide/inject 传递深层数据
  3. 提取公共逻辑到 composables

实现步骤

步骤1创建 ConnectionTree.vue

已完成,组件位置:components/ConnectionTree.vue

步骤2创建 SqlEditor.vue

需要提取的代码:

  • 编辑器相关initEditor, editorView, tabs, activeTab
  • 标签页管理handleAddTab, handleDeleteTab
  • 执行方法handleExecute, handleExecuteSelected通过emit传递SQL给父组件
  • 格式化handleFormat
  • SQL插入insertSQL用于接收表选择事件

步骤3创建 ResultPanel.vue

需要提取的代码:

  • 结果展示resultLoading, resultError, resultData, resultMode, resultStats, resultColumns
  • 消息列表messages
  • 格式化formatJSON

步骤4重构 index.vue

  • 移除已提取的代码
  • 引入新组件
  • 实现组件通信逻辑:
    • 监听 ConnectionTree 的事件
    • 调用 ExecuteSQL API
    • 传递数据到 ResultPanel

通信示例代码

index.vue 中的通信代码

<template>
  <a-layout class="db-cli-layout">
    <a-layout-sider :width="280">
      <ConnectionTree
          :current-connection-id="currentConnection?.id"
          @connection-select="handleConnectionSelect"
          @connection-edit="handleConnectionEdit"
          @connection-delete="handleConnectionDelete"
          @table-select="handleTableSelect"
          @new-connection="showConnectionForm = true"
      />
    </a-layout-sider>
    
    <a-layout class="right-layout">
      <a-layout-content>
        <SqlEditor
            :current-connection="currentConnection"
            @execute="handleExecuteSQL"
            @execute-selected="handleExecuteSelectedSQL"
            @sql-insert="handleSQLInsert"
        />
      </a-layout-content>
      
      <a-layout-footer>
        <ResultPanel
            :loading="resultLoading"
            :error="resultError"
            :data="resultData"
            :mode="resultMode"
            :stats="resultStats"
            :messages="messages"
        />
      </a-layout-footer>
    </a-layout>
  </a-layout>
</template>

<script setup>
// 主组件只负责状态管理和组件协调
const currentConnection = ref(null)
const resultLoading = ref(false)
// ... 其他状态

// 连接选择
const handleConnectionSelect = (conn) => {
  currentConnection.value = conn
  // 清空结果
  clearResults()
}

// SQL执行
const handleExecuteSQL = async (sql) => {
  resultLoading.value = true
  try {
    const result = await window.go.main.App.ExecuteSQL(currentConnection.value.id, sql)
    // 处理结果,更新 resultData, resultStats 等
  } catch (error) {
    // 处理错误
  } finally {
    resultLoading.value = false
  }
}

// SQL插入
const handleSQLInsert = (sql) => {
  // 通过 ref 调用 SqlEditor 的方法
  sqlEditorRef.value?.insertSQL(sql)
}
</script>