vue递归方法实现:
VUE中递归算法实现树形菜单的写法:
<template> <div> <!-- 父组件将数据传入子组件 --> <tree :msg='msg' /> </div> </template> <script> export default { data (){ //模拟数据 return{ n:0, msg: [{name:'北京', sub:[{name:'东城区', sub:[ {name:'朝阳区'} ] },{name:'西城区', sub:[ {name:'关虎屯'} ] },{name:'南城区'},{name:'北城区'}] } ,{ name:'广东', sub:[{name:'广州', sub:[{name:'越秀区'},{name:'白云区'},{name:'海珠区'}] }, {name:'深圳', sub:[{name:'蛇口区'},{name:'保安区'},{name:'盐田区'}] }, ] },{ name:'湖北', sub:[{name:'武汉', sub:[{name:'江夏区'},{name:"洪山区"},{name:'江汉区'}] }, {name:'天门市', sub:[{name:'精灵'},{name:"小班"},{name:'打扮'}] }] }], } }, // 注册父组件 components: { tree:{ name:'gs',//递归的构造函数名 //父组件模板,相当于构造函数return的值 template:` <ul> <li v-for="(v,i) in msg" :key=i @click.stop.self='n=i'> //第一层的数据,点击之后,子集菜单会展开,其他子集菜单会关闭 {{v.name}} <gs :msg=v.sub v-if="i==n"/>//将下一层数据传入构造函数,进行调用,形成递归,相当于自己调用自己,这一步是最关键的一步, </li> </ul> `, props: ['msg'],//接受父组件传的值 data(){ return{ n:0 //默认展开的菜单下标 } } }, } } </script>
方法二:
APP.vue
<template> <div id="app"> <Home :items="items"></Home> </div> </template> <script> import Home from "./components/Home.vue"; export default { name: "App", data() { return { items: [ { name: "IT互联网", child: [ { name: "编辑语言", child: [ { name: "java" }, { name: "c#/ .net" }, { name: "python" }, ], }, { name: "前端开发", child: [{ name: "jq" }, { name: "vue " }, { name: "react " }], }, { name: "移动开发", child: [{ name: " android开发" }, { name: "IOS开发" }], }, { name: "游戏开发", child: [ { name: " phaser游戏开发" }, { name: "webGL游戏开发", child: [{ name: "3D游戏" }] }, ], }, ], }, ], }; }, components: { Home, }, }; </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>
Home.vue
<template> <div class="lists"> <Item v-for="(v, i) in items" :key="i" :item="v"></Item> </div> </template> <script> import Item from "./Item"; export default { name: "", components: { Item }, data() { return {}; }, props: ["items"], }; </script> <style></style>
Item.vue
<template> <ul> <li> <div>{{ item.name }}</div> <Item v-for="(v, i) in item.child" :key="i" :item="v"></Item> </li> </ul> </template> <script> export default { name: "Item", components: {}, data() { return {}; }, props: ["item"], }; </script> <style></style>
JS递归方法实现:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <button onclick="fun()">递归测试</button> <div id="div"> </div> <script> //模拟数据 var data = [{ name: 1, sub: [{ name: '1-1', sub: [] }] }, { name: 2, sub: [{ name: "2-1", sub: [{ name: '2-1-1', sub: [] }, { name: '2-1-2', sub: [] } ] }, { name: "2-2", sub: [{ name: '2-2-1', sub: [] }, { name: '2-2-2', sub: [{ name: '2-2-2-1', sub: [] }] }] } ] }, { name: 3, sub: [] }] var div = document.getElementById('div') var str = '';
//递归函数function list(data) { if (data) { if (data.length > 0) { str += "<ul>"; for (let v = 0; v < data.length; v++) { const item = data[v]; str += '<li>' + item.name; list(item.sub) str += '</li>'; } str += "</ul>"; } } } list(data) console.log(str) div.innerHTML = str;
//以下是递归测试函数,与树形菜单无关 var arr = []; function fun() { var num = parseFloat(prompt("输入数字:")); if (typeof(num) == 'number') { while (num > 0) { arr.push(num) num--; } //console.log(arr) } } var arrlist = []; // var data=[1,[2,3],[4,[5,6,[8]]],9,[10]]; var fun3 = arr => [...arr].map((item) => Array.isArray(item) ? fun3(item) : arrlist.push(item)); fun3(data) // console.log( fun3(data)) </script> </body> </html>
使用VUE + element-ui 实现树形菜单:
<template> <div class="custom-tree-container"> <div class="block"> <p>使用 render-content</p> <el-tree :data="data" show-checkbox node-key="id" default-expand-all :expand-on-click-node="false" :render-content="renderContent" ></el-tree> </div> <div class="block"> <p>使用 scoped slot</p> <el-tree :data="data" show-checkbox node-key="id" default-expand-all :expand-on-click-node="false" > <span class="custom-tree-node" slot-scope="{ node, data }"> <span>{{ node.label }}</span> <span> <el-button type="text" size="mini" @click="() => append(data)">Append</el-button> <el-button type="text" size="mini" @click="() => remove(node, data)">Delete</el-button> </span> </span> </el-tree> </div> <button @click="getAdd">+</button> <button @click="getjian">-</button> </div> </template> <script> let id = 1000; export default { data() { const data = [ { name: "北京", sub: [ { name: "北京", sub: [ { name: "东城区" }, { name: "西城区" }, { name: "南城区" }, { name: "北城区" } ] } ] }, { name: "广东", sub: [ { name: "广州", sub: [{ name: "越秀区" }, { name: "白云区" }, { name: "海珠区" }] }, { name: "深圳", sub: [{ name: "蛇口区" }, { name: "保安区" }, { name: "盐田区" }] } ] }, { name: "湖北", sub: [ { name: "武汉", sub: [{ name: "江夏区" }, { name: "洪山区" }, { name: "江汉区" }] }, { name: "天门市", sub: [{ name: "精灵" }, { name: "小班" }, { name: "打扮" }] } ] } ]; //关键部分 let _data = function(data) { return data.map(v => { if (v.sub) { // 遍历数据,将菜单数据赋值给 ui框架指定属性名 v.label = v.name; v.children = v.sub; return _data(v.sub); } if (v.name && !v.sub) { v.label = v.name; return 123; } }); }; _data(data); return { data: JSON.parse(JSON.stringify(data)), //将处理过的数据进行深刻隆 data: JSON.parse(JSON.stringify(data)) }; }, methods: { append(data) { const newChild = { id: id++, label: "testtest", children: [] }; if (!data.children) { this.$set(data, "children", []); } data.children.push(newChild); }, remove(node, data) { const parent = node.parent; const children = parent.data.children || parent.data; const index = children.findIndex(d => d.id === data.id); children.splice(index, 1); }, renderContent(h, { node, data, store }) { return ( <span class="custom-tree-node"> <span>{node.label}</span> <span> <el-button size="mini" type="text" on-click={() => this.append(data)} > Append </el-button> <el-button size="mini" type="text" on-click={() => this.remove(node, data)} > Delete </el-button> </span> </span> ); }, getAdd() { this.$store.commit("increment"); console.log("我是加法" + this.$store.state.count); }, getjian() { this.$store.commit("jian", 2); console.log("我是加Z法" + this.$store.state.count); } }, mounted() { console.log(this.$store.state.count); } }; </script> <style> .custom-tree-node { flex: 1; display: flex; align-items: center; justify-content: space-between; font-size: 14px; padding-right: 8px; } </style>
js 实现无极限目录树完整版
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> div { margin-left: 20px; cursor: pointer; } .has-child { position: relative; } .has-child::before { content: '+'; position: absolute; left: -20px; } .has-child > div { display: none; } .has-child.expend > div { display: block; } .has-child.expend::before { content: '-'; } </style> </head> <body> <div id="demo"></div> <script> var data = [{ name: '一级标题1', children: [{ name: '二级标题1', children: [{ name: '三级标题' }] }, { name: '二级标题2', children: [{ name: '三级标题' }] }] }, { name: '一级标题2', children: [{ name: '二级标题1', children: [{ name: '三级标题', children: { name: '四级标题' } }] }] }, { name: '一级标题3', children: [{ name: '二级标题1', children: [{ name: '三级标题' }] }, { name: '二级标题2', children: [{ name: '三级标题' }] }, { name: '二级标题3' }] }] // 用来创建目录树结构的函数 /** * data 目录树的数据 * parentNode: 将目录树结构插入到哪个节点下 */ function dTree(data, parentNode) { // 做一个兼容 如果当前没有传递父节点则创建一个父节点 if (!parentNode) { parentNode = document.createElement('div'); parentNode.className = 'root'; } // 遍历数据中的每一项创建目录树的结构 data.forEach(function (item) { var node = document.createElement('div'); node.innerText = item.name; // 阻止事件冒泡 node.onclick = function (e) { e.stopPropagation(); } // 判断当前标题下面是否含有子标题如果含有的话继续创建标题结构 if(item.children && item.children.length > 0) { // 如果含有子标题则添加一个has-child的类名 node.className = 'has-child'; // 如果含有子标题则当前的标题可以点击展开 node.onclick = function (e) { e.stopPropagation(); if (this.classList.contains('expend')) { this.classList.remove('expend') } else { this.classList.add('expend') } } // 如果有子标题的话 需要继续创建子标题的结构 dTree(item.children, node); } parentNode.appendChild(node); }) // 当前函数直接返回创建出来的目录树结构 由于所有的结构都插入到了父节点当中,因此可以返回父节点 return parentNode } var demo = document.getElementById('demo'); dTree(data, demo); </script> </body> </html>
...