最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue3?+?Element?Plus?實(shí)現(xiàn)可搜索、可折疊、可拖拽的部門樹組件功能

 更新時(shí)間:2025年08月18日 10:50:48   作者:....492  
本文給大家介紹Vue3?+?Element?Plus?實(shí)現(xiàn)可搜索、可折疊、可拖拽的部門樹組件,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧

Vue3 + Element Plus 實(shí)現(xiàn)可搜索、可折疊、可拖拽的部門樹組件

在后臺(tái)管理系統(tǒng)中,左側(cè)樹型菜單是常見的 UI 組件。本文將手把手教你使用 Vue3 + Element Plus 來實(shí)現(xiàn)一個(gè)美觀、可搜索、可折疊、可拖拽的部門樹組件。

功能特點(diǎn)

我們的樹組件具有以下功能:

  1. 可搜索:輸入部門名稱實(shí)時(shí)過濾樹節(jié)點(diǎn)。
  2. 選中高亮:點(diǎn)擊節(jié)點(diǎn)高亮顯示,選中狀態(tài)可切換。
  3. 可折疊/展開:可以收起左側(cè)樹,也可以展開。
  4. 可拖拽調(diào)整寬度:鼠標(biāo)拖拽可以改變樹的寬度。
  5. 美觀風(fēng)格:簡(jiǎn)潔清爽,箭頭和葉子圖標(biāo)統(tǒng)一。

組件目錄結(jié)構(gòu)

假設(shè)組件命名為 DeptTree.vue,父組件使用 el-container 布局:

---
## 代碼實(shí)現(xiàn)
下面是完整的 `DeptTree.vue` 代碼:
```vue
<!-- DeptTree.vue -->
<template>
  <el-aside :style="{ width: leftWidth + 'px', height: props.height }" class="left-pane">
    <!-- 搜索 -->
    <el-input
      v-if="props.showFilter"
      v-model="deptName"
      placeholder="請(qǐng)輸入部門名稱"
      clearable
      size="small"
      prefix-icon="Search"
      class="filter-tree"
    />
    <!-- 樹 -->
    <el-tree
      ref="deptTreeRef"
      :data="deptOptions"
      :props="{ label: 'name', children: 'children' }"
      node-key="id"
      highlight-current
      :default-expanded-keys="expandedKeys"
      @node-click="onNodeClick"
      :filter-node-method="filterNode"
      :expand-on-click-node="false"
    >
      <template #default="{ node }">
        <div
          class="tree-node"
          :class="{ 'is-current': node.isCurrent }"
          @click.stop="selectNode(node)"
        >
          <el-icon v-if="node.children && node.children.length" class="arrow">
            <component :is="node.expanded ? ArrowDown : ArrowRight" />
          </el-icon>
          <el-icon v-else class="leaf"><Tickets /></el-icon>
          <span class="label">{{ node.label }}</span>
        </div>
      </template>
    </el-tree>
  </el-aside>
  <!-- 拖拽欄 -->
  <div class="resize-bar" @mousedown="startResize">
    <el-icon class="collapse-icon" @click.stop="toggleCollapse">
      <component :is="leftWidth === 0 ? ArrowRight : ArrowLeft" />
    </el-icon>
  </div>
</template>
<script setup>
import { ref, defineProps, defineEmits, watch } from "vue";
import { ArrowLeft, ArrowRight, ArrowDown, Tickets, Search } from "@element-plus/icons-vue";
const props = defineProps({
  deptOptions: Array,
  leftWidth: { type: Number, default: 280 },
  height: { type: String, default: "100%" },
  showFilter: { type: Boolean, default: true },
  defaultExpand: { type: Boolean, default: false },
});
const emit = defineEmits(["node-click", "update:leftWidth"]);
const deptName = ref("");
const deptTreeRef = ref(null);
const leftWidth = ref(props.leftWidth);
const expandedKeys = ref([]);
// 默認(rèn)展開一級(jí)
watch(() => props.deptOptions, val => {
  if (val?.length) expandedKeys.value = val.map(i => i.id);
}, { immediate: true });
// 過濾節(jié)點(diǎn)
const filterNode = (val, data) => !val || data.name.includes(val);
watch(deptName, val => deptTreeRef.value?.filter(val));
// 拖拽
let startX = 0, isResizing = false;
const startResize = e => {
  isResizing = true;
  startX = e.clientX;
  document.addEventListener("mousemove", updateResize);
  document.addEventListener("mouseup", stopResize);
};
const updateResize = e => {
  if (!isResizing) return;
  leftWidth.value += e.clientX - startX;
  startX = e.clientX;
};
const stopResize = () => {
  isResizing = false;
  document.removeEventListener("mousemove", updateResize);
  document.removeEventListener("mouseup", stopResize);
};
// 折疊/展開
const toggleCollapse = () => {
  leftWidth.value = leftWidth.value === 0 ? 280 : 0;
  emit("update:leftWidth", leftWidth.value);
};
// 節(jié)點(diǎn)選中邏輯
const clearCurrent = nodes => nodes?.forEach(n => {
  n.isCurrent = false;
  n.children && clearCurrent(n.children);
});
const selectNode = node => {
  clearCurrent(props.deptOptions);
  node.isCurrent = true;
  emit("node-click", node);
};
const onNodeClick = node => selectNode(node);
</script>
<style scoped lang="scss">
.left-pane { background:#fff; overflow:hidden; border-right:1px solid #eee; padding:12px; }
.filter-tree { margin-bottom:12px; }
.tree-node {
  display:flex; align-items:center; padding:4px 8px; border-radius:4px; cursor:pointer; transition: all .2s;
  &.is-current { background:#f0f5ff; color:var(--el-color-primary); }
  &:hover { background:#f5f7fa; }
  .arrow, .leaf { font-size:14px; margin-right:6px; }
  .label { flex:1; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; font-size:14px; }
}
.resize-bar { width:8px; cursor:ew-resize; background:#f0f2f5; display:flex; align-items:center; justify-content:center; }
.collapse-icon { font-size:20px; color:#aaa; cursor:pointer; padding:4px; }
</style>

功能分析

1. 樹結(jié)構(gòu)渲染

  • 使用 el-tree 渲染數(shù)據(jù)。
  • props 指定標(biāo)簽和子節(jié)點(diǎn)。
  • 使用 node-key 保證每個(gè)節(jié)點(diǎn)唯一。
  • 通過 highlight-current 高亮選中節(jié)點(diǎn)。

2. 搜索過濾

  • 使用 filter-node-method 實(shí)現(xiàn)關(guān)鍵字過濾。
  • 搜索框綁定 deptName,實(shí)時(shí)調(diào)用 treeRef.filter(val)。

3. 節(jié)點(diǎn)選中高亮

  • 點(diǎn)擊節(jié)點(diǎn)觸發(fā) selectNode。
  • 使用遞歸函數(shù)清空其他節(jié)點(diǎn)的 isCurrent,保證只有當(dāng)前節(jié)點(diǎn)高亮。

4. 可折疊與拖拽

  • 左側(cè)寬度 leftWidth 可通過拖拽調(diào)整。
  • 點(diǎn)擊折疊圖標(biāo)可以收起或展開樹。
  • 鼠標(biāo)拖動(dòng)監(jiān)聽 mousemove,動(dòng)態(tài)更新寬度。

5. 樣式優(yōu)化

  • 父容器 el-aside 背景白色,樹節(jié)點(diǎn)圓角和 hover 高亮。
  • 箭頭和葉子節(jié)點(diǎn)圖標(biāo)統(tǒng)一,界面簡(jiǎn)潔現(xiàn)代。
  • 選中節(jié)點(diǎn)顏色與 Element Plus 主色調(diào)一致。

6. 父組件使用示例

<template>
  <el-container style="height: 100vh">
    <DeptTree
      :deptOptions="deptOptions"
      :leftWidth="leftWidth"
      ref="deptTreeRef"
      @node-click="handleNodeClick"
    />
    <el-main>
      <h3>右側(cè)內(nèi)容區(qū)域</h3>
    </el-main>
  </el-container>
</template>
<script setup>
import { ref } from "vue";
import DeptTree from "./components/DeptTree.vue";
const deptOptions = ref([
  { id: 1, name: "技術(shù)部", children: [{ id: 11, name: "前端組" }, { id: 12, name: "后端組" }] },
  { id: 2, name: "市場(chǎng)部" },
]);
const leftWidth = ref(280);
const handleNodeClick = node => console.log("點(diǎn)擊節(jié)點(diǎn)", node);
</script>

總結(jié)與效果

通過 Vue3 + Element Plus,我們實(shí)現(xiàn)了一個(gè)可搜索、可選中高亮、可折疊、可拖拽的部門樹組件

組件特點(diǎn):

  • 邏輯清晰,代碼優(yōu)雅;
  • 樣式現(xiàn)代美觀;
  • 可復(fù)用性強(qiáng),可快速應(yīng)用到后臺(tái)系統(tǒng)。

效果展示

  • 搜索過濾效果
    • 輸入部門名稱即可實(shí)時(shí)過濾樹節(jié)點(diǎn),便于快速定位目標(biāo)部門。
  • 選中高亮效果
    • 點(diǎn)擊節(jié)點(diǎn)高亮顯示,之前選中的節(jié)點(diǎn)高亮?xí)詣?dòng)取消,保證視覺清晰。
  • 折疊與展開效果
    • 點(diǎn)擊左側(cè)折疊按鈕即可收起或展開樹,界面簡(jiǎn)潔靈活。
  • 拖拽調(diào)整寬度效果
    • 鼠標(biāo)拖拽左側(cè)樹邊緣可以調(diào)整寬度,適應(yīng)不同屏幕布局。

到此這篇關(guān)于Vue3 + Element Plus 實(shí)現(xiàn)可搜索、可折疊、可拖拽的部門樹組件的文章就介紹到這了,更多相關(guān)vue elementplus部門樹組件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

安仁县| 淮南市| 纳雍县| 嘉义市| 安溪县| 榆林市| 河源市| 巴中市| 富裕县| 来宾市| 金秀| 红河县| 罗江县| 大城县| 隆化县| 衢州市| 红安县| 临江市| 新沂市| 象山县| 霍邱县| 泰兴市| 平阳县| 广东省| 永善县| 黄平县| 蒙山县| 许昌县| 龙泉市| 盘山县| 德令哈市| 黎城县| 福海县| 兴化市| 奎屯市| 嘉黎县| 喀喇沁旗| 奇台县| 绥化市| 孝昌县| 鄯善县|