【Vue】-组件开发-一个树组件

devtools/2024/11/15 3:52:47/

我们来自己搞一个树组件

1. 创建 Vue 项目

如果你还没有创建 Vue 项目,可以使用 Vue CLI 快速创建:

vue create my-tree-component
cd my-tree-component

2. 安装依赖

确保安装了 Vue Router 和 Vuex(如果需要状态管理):

npm install vue-router vuex --save

3. 创建 Tree 组件

src/components 目录下创建 Tree.vue 文件:

<template><div class="tree"><ul><tree-node v-for="node in data" :key="node.id" :node="node"></tree-node></ul></div>
</template><script>
import TreeNode from './TreeNode.vue';export default {name: 'Tree',components: {TreeNode},props: {data: {type: Array,required: true}}
};
</script><style scoped>
.tree ul {list-style-type: none;padding-left: 20px;
}
</style>

4. 创建 TreeNode 组件

src/components 目录下创建 TreeNode.vue 文件:

<template><li><span @click="toggle">{{ node.name }}</span><ul v-if="isOpen"><tree-node v-for="child in node.children" :key="child.id" :node="child"></tree-node></ul></li>
</template><script>
export default {name: 'TreeNode',props: {node: {type: Object,required: true}},data() {return {isOpen: false};},methods: {toggle() {this.isOpen = !this.isOpen;}}
};
</script><style scoped>
li {cursor: pointer;
}
</style>

5. 使用 Tree 组件

src/App.vue 中使用 Tree 组件:

<template><div id="app"><tree :data="treeData"></tree></div>
</template><script>
import Tree from './components/Tree.vue';export default {name: 'App',components: {Tree},data() {return {treeData: [{id: 1,name: 'Node 1',children: [{ id: 2, name: 'Child Node 1' },{ id: 3, name: 'Child Node 2' }]},{id: 4,name: 'Node 2',children: [{ id: 5, name: 'Child Node 3' }]}]};}
};
</script><style>
#app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px;
}
</style>

6. 运行项目

运行项目以查看效果:

npm run serve

7. 功能扩展

  • 搜索功能:添加一个搜索框,根据输入过滤树节点。
  • 拖拽排序:使用第三方库如 vuedraggable 实现节点的拖拽排序。
  • 懒加载:对于大型树结构,可以实现懒加载,仅在展开节点时加载子节点数据。

功能扩展的实现

1. 搜索功能

修改 Tree.vue 组件

Tree.vue 中添加一个搜索框,并根据输入过滤树节点。

<template><div class="tree"><input type="text" v-model="searchQuery" placeholder="Search..." /><ul><tree-node v-for="node in filteredData" :key="node.id" :node="node"></tree-node></ul></div>
</template><script>
import TreeNode from './TreeNode.vue';
import { filterTree } from '@/utils/treeUtils';export default {name: 'Tree',components: {TreeNode},props: {data: {type: Array,required: true}},data() {return {searchQuery: ''};},computed: {filteredData() {if (!this.searchQuery) return this.data;return filterTree(this.data, this.searchQuery);}}
};
</script><style scoped>
.tree ul {list-style-type: none;padding-left: 20px;
}
</style>
创建 treeUtils.js 工具文件

src/utils 目录下创建 treeUtils.js 文件,用于实现树节点的过滤功能。

export function filterTree(data, query) {const lowerCaseQuery = query.toLowerCase();return data.filter(node => {if (node.name.toLowerCase().includes(lowerCaseQuery)) {return true;}if (node.children && node.children.length > 0) {node.children = filterTree(node.children, query);return node.children.length > 0;}return false;});
}

2. 拖拽排序

安装 vuedraggable

首先,安装 vuedraggable 库:

npm install vuedraggable
修改 Tree.vue 组件

Tree.vue 中引入 vuedraggable 并使用它来实现拖拽排序。

<template><div class="tree"><input type="text" v-model="searchQuery" placeholder="Search..." /><draggable v-model="filteredData" @change="onDragChange"><tree-node v-for="node in filteredData" :key="node.id" :node="node"></tree-node></draggable></div>
</template><script>
import TreeNode from './TreeNode.vue';
import draggable from 'vuedraggable';
import { filterTree } from '@/utils/treeUtils';export default {name: 'Tree',components: {TreeNode,draggable},props: {data: {type: Array,required: true}},data() {return {searchQuery: '',localData: [...this.data]};},computed: {filteredData: {get() {if (!this.searchQuery) return this.localData;return filterTree(this.localData, this.searchQuery);},set(value) {this.localData = value;}}},methods: {onDragChange(event) {console.log('Drag change:', event);// 处理拖拽后的变化,例如更新父组件的数据this.$emit('update:data', this.localData);}}
};
</script><style scoped>
.tree ul {list-style-type: none;padding-left: 20px;
}
</style>

3. 懒加载

修改 TreeNode.vue 组件

TreeNode.vue 中实现懒加载功能。

<template><li><span @click="toggle">{{ node.name }}</span><ul v-if="isOpen"><draggable v-model="node.children" @change="onDragChange"><tree-node v-for="child in node.children" :key="child.id" :node="child"></tree-node></draggable></ul></li>
</template><script>
import draggable from 'vuedraggable';export default {name: 'TreeNode',components: {draggable},props: {node: {type: Object,required: true}},data() {return {isOpen: false,hasLoadedChildren: false};},methods: {toggle() {if (!this.hasLoadedChildren && this.node.children && this.node.children.length === 0) {this.loadChildren();}this.isOpen = !this.isOpen;},loadChildren() {// 模拟异步加载子节点setTimeout(() => {this.node.children = [{ id: 101, name: 'Lazy Child 1' },{ id: 102, name: 'Lazy Child 2' }];this.hasLoadedChildren = true;}, 1000);},onDragChange(event) {console.log('Drag change:', event);// 处理拖拽后的变化,例如更新父组件的数据this.$emit('update:node', { ...this.node, children: this.node.children });}}
};
</script><style scoped>
li {cursor: pointer;
}
</style>

4. 更新 App.vue

确保 App.vue 中的 Tree 组件能够接收和处理数据更新。

<template><div id="app"><tree :data="treeData" @update:data="updateTreeData"></tree></div>
</template><script>
import Tree from './components/Tree.vue';export default {name: 'App',components: {Tree},data() {return {treeData: [{id: 1,name: 'Node 1',children: [{ id: 2, name: 'Child Node 1' },{ id: 3, name: 'Child Node 2' }]},{id: 4,name: 'Node 2',children: [{ id: 5, name: 'Child Node 3' }]}]};},methods: {updateTreeData(newData) {this.treeData = newData;}}
};
</script><style>
#app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px;
}
</style>

5. 运行项目

运行项目以查看效果:

npm run serve

基本的功能就都具备了,当然实际生产中可能会碰到各种新的需求,慢慢来扩展即可。


http://www.ppmy.cn/devtools/133245.html

相关文章

Java 中的 transient 关键字:深入解析与实战

在 Java 编程中&#xff0c;transient 关键字是一个非常有用的工具&#xff0c;尤其是在处理对象序列化时。尽管 transient 关键字在日常开发中可能不常被使用&#xff0c;但了解它的作用和使用场景对于提升代码的安全性和性能至关重要。本文将深入探讨 transient 关键字的作用…

【网络-交换机】生成树协议、环路检测

路由优先级 路由优先级决定了在多种可达的路由类型中&#xff0c;哪种路由将被用来转发数据包。路由优先级值越低&#xff0c;对应路由的优先级越高&#xff0c;优先级值255表示对应的路由不可达。一般情况下&#xff0c;静态路由的优先级为1&#xff0c;OSPF路由优先级为110&a…

gan的所有种类,人工智能 机器学习,gan的所有算法

参考最全汇总GAN网络及其各种变体&#xff08;附论文及代码实现&#xff09;_gan网络代码-CSDN博客 这是我找到的关于您提问的答案: 1. **GAN类型**: Auxiliary Classifier GAN **参考论文**: 《Conditional Image Synthesis With Auxiliary Classifier GANs》 **代码地址**: …

基于Redis缓存机制实现高并发接口调试

创建接口 这里使用的是阿里云提供的接口服务直接做的测试&#xff0c;接口地址 curl http://localhost:8080/initData?tokenAppWithRedis 这里主要通过参数cacheFirstfalse和true来区分是否走缓存&#xff0c;正常的业务机制可能是通过后台代码逻辑自行控制的&#xff0c;这…

Zookeeper笔记

一、Zookeeper概述 - 定义&#xff1a;Zookeeper是一个分布式的、开源的分布式应用程序协调服务。它主要用于管理和协调分布式系统中的各种服务&#xff0c;提供诸如配置管理、命名服务、分布式锁等功能。 - 应用场景举例&#xff1a;在Hadoop生态系统中&#xff0c;用于协调H…

舜宇光学科技入职测评:北森商业推理40分钟28题真题解析、网盘资料下载、答题技巧

舜宇光学科技的北森商业推理测评主要考察应聘者的商业推理能力&#xff0c;具体内容包括以下几个方面&#xff1a; 1. **言语能力题**&#xff1a;主要考察语言理解和表达能力&#xff0c;包含阅读理解、完形填空等。 2. **图形推理题**&#xff1a;给出一组图形&#xff0c;…

rabbitMq怎么保证消息不丢失?消费者没有接收到消息怎么处理

在使用RabbitMQ时&#xff0c;保证消息不丢失以及处理消费者未接收到消息的情况可以通过以下几个方法&#xff1a; 1. 确保消息的持久化 队列持久化&#xff1a;在声明队列时将其设置为持久化&#xff08;durabletrue&#xff09;&#xff0c;这样RabbitMQ在重启后也会保留队…

Java中 ==和equals的区别?

目录 1. 运算符 用法 对象的比较 基本数据类型的比较 2. equals() 方法 用法 equals() 的重写 3. 和 equals() 的实际区别 示例&#xff1a; 和 equals() 的区别 小结&#xff1a; 1. 运算符 用法 是 比较运算符&#xff0c;它用于比较两个对象的 引用是否相同&…