首页
/ AnotherRedisDesktopManager 连接列表组件:管理所有 Redis 连接

AnotherRedisDesktopManager 连接列表组件:管理所有 Redis 连接

2026-02-04 05:13:40作者:曹令琨Iris

组件概述

Connections(连接列表)组件是 AnotherRedisDesktopManager 中负责管理所有 Redis 服务器连接的核心界面组件。它位于应用左侧导航区域,提供连接的可视化管理、搜索过滤、排序调整等功能,是用户与 Redis 服务器交互的入口点。该组件通过 Vue.js 框架构建,结合 Element UI 组件库实现界面渲染,使用本地存储(storage)持久化连接配置,并通过事件总线(bus)实现跨组件通信。

组件结构与核心功能

组件文件结构

src/components/
├── Connections.vue         # 连接列表主组件
├── ConnectionWrapper.vue   # 单个连接项包装器
├── ConnectionMenu.vue      # 连接右键菜单
└── NewConnectionDialog.vue # 新建连接对话框

核心功能模块

功能模块 描述 技术实现
连接列表渲染 展示所有已保存的 Redis 连接 v-for 循环渲染 ConnectionWrapper 组件
搜索过滤 根据连接名称实时筛选连接 计算属性 filteredConnections + 字符串 includes 匹配
拖拽排序 支持通过拖拽调整连接顺序 SortableJS 实现拖拽功能
状态同步 响应全局设置变更和连接更新 EventBus 事件监听(refreshConnections/reloadSettings)
本地存储 持久化保存连接配置和排序 storage 模块读写本地数据

组件实现解析

模板结构(Template)

<template>
  <div class="connections-wrap">
    <!-- 搜索框:当连接数超过阈值时显示 -->
    <div v-if="connections.length>=filterEnableNum" class="filter-input">
      <el-input
        v-model="filterMode"
        suffix-icon="el-icon-search"
        :placeholder="$t('message.search_connection')"
        clearable
        size="mini">
      </el-input>
    </div>

    <!-- 连接列表容器 -->
    <div class="connections-list">
      <ConnectionWrapper
        v-for="item, index of filteredConnections"
        :key="item.key ? item.key : item.connectionName"
        :index="index"
        :globalSettings="globalSettings"
        :config='item'>
      </ConnectionWrapper>
    </div>

    <!-- 回到顶部按钮 -->
    <ScrollToTop parentNum='1' :posRight='false'></ScrollToTop>
  </div>
</template>

模板结构采用三层布局:顶部搜索区、中间连接列表区和底部回到顶部按钮。搜索框通过条件渲染(v-if)控制显示,仅当连接数超过 filterEnableNum(默认4个)时才显示。连接列表使用 v-for 循环渲染 ConnectionWrapper 子组件,每个子组件对应一个 Redis 连接配置。

数据与状态管理(Script)

核心数据属性

data() {
  return {
    connections: [],          // 所有连接配置数组
    globalSettings: {},       // 全局设置对象
    filterEnableNum: 4,       // 启用搜索框的连接数阈值
    filterMode: ''            // 搜索过滤关键词
  };
}

计算属性:过滤连接列表

computed: {
  filteredConnections() {
    if (!this.filterMode) return this.connections;
    // 不区分大小写的名称匹配
    return this.connections.filter(item => 
      item.name.toLowerCase().includes(this.filterMode.toLowerCase())
    );
  }
}

方法:初始化与排序

methods: {
  // 从本地存储加载连接配置
  initConnections() {
    const connections = storage.getConnections(true);
    const slovedConnections = [];
    for (const item of connections) {
      item.connectionName = storage.getConnectionName(item);
      delete item.db; // 修复历史版本bug,移除冗余db字段
      slovedConnections.push(item);
    }
    this.connections = slovedConnections;
  },
  
  // 初始化拖拽排序功能
  sortOrder() {
    const dragWrapper = document.querySelector('.connections-wrap .connections-list');
    Sortable.create(dragWrapper, {
      handle: '.el-submenu__title', // 拖拽手柄:连接项标题栏
      animation: 400,               // 动画时长
      direction: 'vertical',        // 垂直方向拖拽
      onEnd: (e) => {               // 拖拽结束回调
        const { newIndex, oldIndex } = e;
        // 调整数组顺序
        const [movedItem] = this.connections.splice(oldIndex, 1);
        this.connections.splice(newIndex, 0, movedItem);
        // 保存新顺序到本地存储
        this.$storage.reOrderAndStore(this.connections);
      }
    });
  }
}

生命周期与事件监听

created() {
  // 监听连接更新事件
  this.$bus.$on('refreshConnections', () => this.initConnections());
  // 监听全局设置变更事件
  this.$bus.$on('reloadSettings', (settings) => this.globalSettings = settings);
},

mounted() {
  this.initConnections(); // 初始化连接数据
  this.sortOrder();       // 初始化拖拽排序
}

样式设计(Style)

.connections-wrap {
  height: calc(100vh - 59px);  /* 计算高度:视口高度 - 顶部导航栏高度 */
  overflow-y: auto;            /* 垂直滚动 */
  margin-top: 11px;
}

.connections-wrap .filter-input {
  padding-right: 13px;
  margin-bottom: 4px;
}

/* 设置拖拽区域最小高度,确保拖拽到末尾时位置正确 */
.connections-wrap .connections-list {
  min-height: calc(100vh - 110px);
}

组件交互流程

连接加载与渲染流程

sequenceDiagram
  participant Connections
  participant storage
  participant ConnectionWrapper
  
  Connections->>Connections: mounted()
  Connections->>Connections: initConnections()
  Connections->>storage: getConnections(true)
  storage-->>Connections: 返回连接配置数组
  Connections->>ConnectionWrapper: v-for 渲染每个连接
  ConnectionWrapper-->>Connections: 渲染完成

拖拽排序数据流向

flowchart TD
  A[用户拖拽连接项] --> B[SortableJS 触发 onEnd 事件]
  B --> C[调整 connections 数组顺序]
  C --> D[调用 $storage.reOrderAndStore]
  D --> E[更新本地存储]
  E --> F[下次加载时保持新顺序]

性能优化策略

  1. 条件渲染搜索框:通过 v-if="connections.length>=filterEnableNum" 控制搜索框显示,减少少量连接时的DOM节点数量。

  2. 计算属性缓存:使用 Vue 计算属性的缓存机制,避免每次输入都重新过滤整个连接列表。

  3. 最小化DOM操作:通过 SortableJS 实现高效拖拽,仅在拖拽结束时执行一次数组重排和本地存储更新。

  4. 样式优化:使用 min-height 确保拖拽目标区域大小稳定,避免拖拽过程中出现布局抖动。

常见问题与解决方案

问题1:连接排序在刷新后丢失

原因:未正确将排序结果持久化到本地存储。

解决方案:在拖拽结束事件中调用 this.$storage.reOrderAndStore(this.connections),将新顺序保存到本地存储。

onEnd: (e) => {
  // 调整数组顺序
  const [movedItem] = this.connections.splice(oldIndex, 1);
  this.connections.splice(newIndex, 0, movedItem);
  // 关键:保存新顺序到本地存储
  this.$storage.reOrderAndStore(this.connections);
}

问题2:搜索过滤不区分大小写

解决方案:统一转换为小写后再进行匹配:

return this.connections.filter(item => 
  item.name.toLowerCase().includes(this.filterMode.toLowerCase())
);

问题3:大量连接时渲染性能下降

优化方向

  • 实现虚拟滚动(使用 el-virtual-scroller)
  • 添加连接分组功能,减少单次渲染数量
  • 使用 key 属性优化 Vue 的 DOM 复用机制

扩展功能建议

  1. 连接分组管理:支持创建连接文件夹,按环境(开发/测试/生产)或项目对连接进行分组管理。

  2. 连接健康状态指示:在连接名称旁显示 Redis 服务器状态(在线/离线/高负载),通过定期 ping 命令检测。

  3. 批量操作:添加批量删除、批量导出连接配置功能,提高多连接管理效率。

  4. 连接导入导出:支持 JSON 格式导入导出连接配置,方便在不同设备间迁移。

总结

Connections 组件作为 AnotherRedisDesktopManager 的核心组件之一,通过优雅的 Vue 组件设计和高效的数据处理,为用户提供了直观、便捷的 Redis 连接管理界面。其主要特点包括:

  • 模块化设计:通过拆分 Connections/ConnectionWrapper/ConnectionMenu 等组件,实现关注点分离。
  • 响应式交互:结合 SortableJS 和 EventBus 实现流畅的拖拽排序和状态同步。
  • 性能优化:通过条件渲染、计算属性缓存等手段确保组件高效运行。

该组件的实现充分利用了 Vue.js 的响应式系统和组件化思想,同时结合本地存储和第三方库,为用户提供了稳定、易用的连接管理体验。

登录后查看全文
热门项目推荐
相关项目推荐