vue遞歸實(shí)現(xiàn)樹形組件
本文實(shí)例為大家分享了vue遞歸實(shí)現(xiàn)樹形組件的具體代碼,供大家參考,具體內(nèi)容如下
1. 先來看一下效果:
2. 代碼部分 (myTree.vue)
圖片可以自己引一下自己的圖片,或者使用iconfont的css引入。
<template> ? ? <div class="tree"> ? ? ? ? <ul class="ul"> ? ? ? ? ? ? <li v-for="(item,index) of treeMenu" :key="index"> ? ? ? ? ? ? ? ? <div class="jiantou" @click="changeStatus(index)"> ? ? ? ? ? ? ? ? ? ? <img src="../../assets/right.png" v-if="!scopesDefault[index]===true && item.children"> ? ? ? ? ? ? ? ? ? ? <img src="../../assets/down.png" v-if="scopesDefault[index]===true && item.children "> ? ? ? ? ? ? ? ? </div> ? ? ? ? ? ? ? ? <input type="checkbox" @click="checkBox(item)" v-model="item.check"> ? ? ? ? ? ? ? ? <span @click="changeStatus(index)">{{item.label}}</span> ? ? ? ? ? ? ? ? <div class="subtree"> ? ? ? ? ? ? ? ? ? ? <tree-menu :treeMenu='item.children' v-if="scopesDefault[index]" @selectnode = "selectnode"></tree-menu> ? ? ? ? ? ? ? ? </div> ? ? ? ? ? ? </li> ? ? ? ? ? </ul>? ? ? </div>? </template> <script> ?? ?export default{ ? ? name:'treeMenu', ? ? ?props:{ ? ? ? ? treeMenu:{ ? ? ? ? ? ? type:Array, ? ? ? ? ? ? default:[] ? ? ? ? }, ? ? }, ? ? data(){ ? ? ? ? return{ ? ? ? ? ? ? scopesDefault: [], ? ? ? ? ? ? scopes: [],? ? ? ? ? ? ? node:[], ? ? ? ? ? ? flatTreeMenu:[], ? ? ? ? ? ? check:'', ? ? ? ? } ? ? }, ? ? methods:{ ? ? ? ? //展開 ? ? ? ? scope() { ? ? ? ? ? ? this.treeMenu.forEach((item, index) => { ? ? ? ? ? ? ? ? this.scopesDefault[index] = false ? ? ? ? ? ? ? ? if ('children' in item) { ? ? ? ? ? ? ? ? ? ? this.scopes[index] = true ? ? ? ? ? ? ? ? ? ? //console.log(item, index) ? ? ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? ? ? this.scopes[index] = false ? ? ? ? ? ? ? ? } ? ? ? ? ? ? }) ? ? ? ? }, ? ? ? ? changeStatus(index) { ? ? ? ? ? ? if (this.scopesDefault[index] == true) { ? ? ? ? ? ? ? ? this.$set(this.scopesDefault, index, false) ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? this.$set(this.scopesDefault, index, this.scopes[index]) ? ? ? ? ? ? } ? ? ? ? }, ? ? ? ? //nodelist 深度優(yōu)先遞歸 ? ? ? ? checkBox(node,nodelist=[]){ ? ? ? ? ? ? //console.log("start:",node,nodelist) ? ? ? ? ? ? if(node!==null){ ? ? ? ? ? ? ? ? nodelist.push(node); ? ? ? ? ? ? ? ? if(node.children){ ? ? ? ? ? ? ? ? ? ? let children=node.children; ? ? ? ? ? ? ? ? ? ? for(let i=0;i<children.length;i++){ ? ? ? ? ? ? ? ? ? ? ? ? this.checkBox(children[i],nodelist)//遞歸調(diào)用 ? ? ? ? ? ? ? ? ? ? ? ? children[i].check = nodelist[0].check==false?true:false;//選中父節(jié)點(diǎn),子節(jié)點(diǎn)全選,取消,子節(jié)點(diǎn)取消 ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? ? ? this.node=node; ? ? ? ? ? ? this.check=node.check ? ? ? ? }, ? ? ? ? selectnode(node){ ? ? ? ? ? ? this.$emit("selectnode",node); ? ? ? ? } ? ? }, ? ? watch:{? ? ? ? ? node:{ ? ? ? ? ? ? handler(val){ ? ? ? ? ? ? ? ? this.selectnode(val); ? ? ? ? ? ? }, ? ? ? ? ? ? immediate: true ? ? ? ? }, ? ? ? ? check:{ ? ? ? ? ? ? handler(val){ ? ? ? ? ? ? ? ? this.selectnode(this.node); ? ? ? ? ? ? }, ? ? ? ? ? ? immediate: true ? ? ? ? } ? ? }, ? ? mounted(){ ? ? ? ? this.scope();? ? ? } } </script>
<style lang = "scss" scoped> .tree{ ? ? .ul{ ? ? ? ? margin: 5px 0 5px 0; ? ? ? ? >li{ ? ? ? ? ? ? .jiantou{ ? ? ? ? ? ? ? ? display: inline-block; ? ? ? ? ? ? ? ? width: 15px; ? ? ? ? ? ? ? ? >img{ ? ? ? ? ? ? ? ? position: relative; ? ? ? ? ? ? ? ? top: 2.0px; ? ? ? ? ? ? ? ? left: 4px; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? ? ? .subtree{ ? ? ? ? ? ? ? ? margin-left: 20px; ? ? ? ? ? ? ? ? margin-top: 8px; ? ? ? ? ? ? ? ? margin-bottom: 8px; ? ? ? ? ? ? } ? ? ? ? } ? ? } } input[type=checkbox]{ ? ? visibility: hidden; ? ? cursor: pointer; ? ? position: relative; ? ? width: 15px; ? ? height: 15px; ? ? font-size: 14px; ? ? border: 1px solid #dcdfe6; ? ? background-color: #fff !important; ? ? &::after{ ? ? ? ? position: absolute; ? ? ? ? top: 0; ? ? ? ? background-color: #fff; ? ? ? ? border: 1px solid #ddd; ? ? ? ? color: #000; ? ? ? ? width: 15px; ? ? ? ? height: 15px; ? ? ? ? display: inline-block; ? ? ? ? visibility: visible; ? ? ? ? padding-left: 0px; ? ? ? ? text-align: center; ? ? ? ? content: ' '; ? ? ? ? border-radius: 3px; ? ? ? ? transition: all linear .1s; ? ? } ? ? &:checked::after{ ? ? ? ? content: "\2713"; ? ? ? ? font-size: 12px; ? ? ? ? background-color: #409eff; ? ? ? ? border: 1px solid #409eff; ? ? ? ? transition: all linear .1s; ? ? ? ? color: #fff; ? ? ? ? font-weight: bold; ? ? } } .check{ ? ? &:checked::after{ ? ? ? ? content: "--" !important; ? ? } } </style>
講解:
1、調(diào)用組件:
我這用來一個(gè)global.js
來控制組件的使用(這個(gè)js附在文章末尾了),在component
文件夾中建立一個(gè)myTree
文件夾,里面放同名vue文件(myTree.vue
),這樣無論在哪里調(diào)用這個(gè)組件,都可以直接使用<my-tree></my-tree>
的方式去調(diào)用。
2、組件的方法:
scope():
會(huì)生成一個(gè)數(shù)組,里面有根節(jié)點(diǎn)是否有子節(jié)點(diǎn),如本代碼里設(shè)定的數(shù)據(jù),會(huì)有scopes=[true,true,true]
這樣的結(jié)果。changeStatus():
每點(diǎn)擊標(biāo)題或者箭頭,如果當(dāng)前下標(biāo)的節(jié)點(diǎn)有沒有子節(jié)點(diǎn),再將結(jié)果動(dòng)態(tài)賦值給scopesDefault[index]
,將這個(gè)值放于dom上控制開關(guān),遞歸組件。checkBox():
在組件內(nèi)部實(shí)現(xiàn)了點(diǎn)擊全選、點(diǎn)擊取消全選的功能,遞歸調(diào)用當(dāng)前方法,將子元素的狀態(tài)隨父元素一起變化。selectnode():
將當(dāng)前點(diǎn)擊的node的節(jié)點(diǎn)內(nèi)容上傳到父組件。
3、監(jiān)聽:
同時(shí)監(jiān)聽:不同節(jié)點(diǎn)的切換、同一個(gè)節(jié)點(diǎn)的是否選中的切換,監(jiān)聽得到的結(jié)果都傳到父組件中。
4、組件遞歸:調(diào)用時(shí)與父組件相同
3. 使用組件(useMyTree.vue)
<template> ? ? <div class = "loginModuel"> ? ? ? ? <my-tree :treeMenu='tree' @selectnode="selectnode"></my-tree> ? ? </div> </template> <script> export default{ ? ? data(){ ? ? ? ? return{ ? ? ? ? ? ? msg:"這是登錄頁面", ? ? ? ? ? ? tree:[ ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? id:1, ? ? ? ? ? ? ? ? ? ? label:"1級(jí)目錄1", ? ? ? ? ? ? ? ? ? ? check:false, ? ? ? ? ? ? ? ? ? ? children:[ ? ? ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? ? ? id:"1-1", ? ? ? ? ? ? ? ? ? ? ? ? ? ? pid:1, ? ? ? ? ? ? ? ? ? ? ? ? ? ? label:"1.1目錄", ? ? ? ? ? ? ? ? ? ? ? ? ? ? check:false ? ? ? ? ? ? ? ? ? ? ? ? }, ? ? ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? ? ? id:"1-2", ? ? ? ? ? ? ? ? ? ? ? ? ? ? pid:1, ? ? ? ? ? ? ? ? ? ? ? ? ? ? label:"1.2目錄", ? ? ? ? ? ? ? ? ? ? ? ? ? ? check:false ? ? ? ? ? ? ? ? ? ? ? ? }, ? ? ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? ? ? id:"1-3", ? ? ? ? ? ? ? ? ? ? ? ? ? ? pid:1, ? ? ? ? ? ? ? ? ? ? ? ? ? ? label:"1.3目錄", ? ? ? ? ? ? ? ? ? ? ? ? ? ? check:false ? ? ? ? ? ? ? ? ? ? ? ? }, ? ? ? ? ? ? ? ? ? ? ] ? ? ? ? ? ? ? ? }, ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? id:2, ? ? ? ? ? ? ? ? ? label:"1級(jí)目錄2", ? ? ? ? ? ? ? ? ? check:false, ? ? ? ? ? ? ? ? ? children:[ ? ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? ? id:"2-1", ? ? ? ? ? ? ? ? ? ? ? ? ? label:"2.1目錄", ? ? ? ? ? ? ? ? ? ? ? ? ? check:false, ? ? ? ? ? ? ? ? ? ? ? ? ? pid:2, ? ? ? ? ? ? ? ? ? ? ? ? ? children:[ ? ? ? ? ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? id:"2-1-1", ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pid:'2-1', ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? label:"2.1.1目錄", ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? check:false, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? children:[ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? id:"2-1-1-1", ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pid:'2-1-1', ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? label:"2.1.1.1目錄", ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? check:false, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? children:[ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? id:"2-1-1-1-1", ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pid:'2-1-1-1', ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? label:"2.1.1.1.1目錄", ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? check:false, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? id:"2-1-1-1-2", ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pid:'2-1-1-1', ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? label:"2.1.1.1.2目錄", ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? check:false, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ] ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ] ? ? ? ? ? ? ? ? ? ? ? ? ? ? }, ? ? ? ? ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? id:"2-1-2", ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pid:'2-1', ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? label:"2.1.2目錄", ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? check:false, ? ? ? ? ? ? ? ? ? ? ? ? ? ? }, ? ? ? ? ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? id:"2-1-3", ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pid:'2-1', ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? label:"2.1.3目錄", ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? check:false, ? ? ? ? ? ? ? ? ? ? ? ? ? ? }, ? ? ? ? ? ? ? ? ? ? ? ? ] ? ? ? ? ? ? ? ? ? ? ? }, ? ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? ? id:"2-2", ? ? ? ? ? ? ? ? ? ? ? ? ? pid:2, ? ? ? ? ? ? ? ? ? ? ? ? ? label:"2.2目錄", ? ? ? ? ? ? ? ? ? ? ? ? ? check:false ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ] ? ? ? ? ? ? ? },//在此繼續(xù)添加目錄 ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? id:3, ? ? ? ? ? ? ? ? label:"1級(jí)目錄3", ? ? ? ? ? ? ? ? check:false, ? ? ? ? ? ? ? ? children:[ ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? id:"3-1", ? ? ? ? ? ? ? ? ? ? ? ? pid:3, ? ? ? ? ? ? ? ? ? ? ? ? label:"3.1目錄", ? ? ? ? ? ? ? ? ? ? ? ? check:false, ? ? ? ? ? ? ? ? ? ? ? ? children:[ ? ? ? ? ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? id:"3-1-1", ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pid:"3-1", ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? label:"3.1.1目錄", ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? check:false, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? children:[ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? id:"3-1-1-1", ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pid:"3-1-1", ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? label:"3.1.1.1目錄", ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? check:false, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? children:[ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? id:"3-1-1-1-1", ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pid:"3-1-1-1", ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? label:"3.1.1.1.1目錄", ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? check:false ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ] ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ] ? ? ? ? ? ? ? ? ? ? ? ? ? ? }, ? ? ? ? ? ? ? ? ? ? ? ? ] ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ] ? ? ? ? ? ? }, ? ? ? ? ? ? ], ? ? ? ? ? ? plist:[],//此級(jí)以上所有父節(jié)點(diǎn)列表 ? ? ? ? ? ? flatTree:[],//tree的平行數(shù)據(jù) ? ? ? ? ? ? node:'',//當(dāng)前點(diǎn)擊的node, ? ? ? ? } ? ? }, ? ? methods:{ ? ? ? ? //將tree樹形數(shù)據(jù)轉(zhuǎn)換為平行數(shù)據(jù) ? ? ? ? transformData(tree){ ? ? ? ? ? ? tree.forEach(item=>{ ? ? ? ? ? ? ? ? this.flatTree.push(item); ? ? ? ? ? ? ? ? item.children && item.children.length>0 ? this.transformData(item.children) : "" ? ? ? ? ? ? }) ? ? ? ? }, ? ? ? ? //子組件傳遞過來的點(diǎn)擊的node的值 ? ? ? ? selectnode(node){ ? ? ? ? ? ? this.node=node; ? ? ? ? ? ? this.flatTree=[]; ? ? ? ? ? ? this.transformData(this.tree); ? ? ? ? ? ? if(node.check==false){//這個(gè)節(jié)點(diǎn)已經(jīng)被選中,正在點(diǎn)擊取消選中 ? ? ? ? ? ? ? ? this.plist=[];//每次點(diǎn)擊一個(gè)新的節(jié)點(diǎn)都將原來plist的內(nèi)容清空 ? ? ? ? ? ? ? ? this.getParentnode(this.flatTree,node.pid) ? ? ? ? ? ? }else{//正在選中 ? ? ? ? ? ? ? ? this.childAllToParent(node,this.flatTree,1); ? ? ? ? ? ? } ? ? ? ? }, ? ? ? ? //子節(jié)點(diǎn)取消選中,拿到此子節(jié)點(diǎn)所有的父節(jié)點(diǎn)plist ? ? ? ? getParentnode(tree,pid){ ? ? ? ? ? ? //this.plist=[] ? ? ? ? ? ? if(pid!==null){ ? ? ? ? ? ? ? ? tree.forEach(item=>{ ? ? ? ? ? ? ? ? ? ? if(item.id==pid){ ? ? ? ? ? ? ? ? ? ? ? ? this.plist.push(item) ? ? ? ? ? ? ? ? ? ? ? ? this.getParentnode(this.flatTree,item.pid) ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? }) ? ? ? ? ? ? }? ? ? ? ? ? ? if(!pid){ ? ? ? ? ? ? ? ? this.plist.forEach(item=>{ ? ? ? ? ? ? ? ? ? ? this.updateParentCheck(this.tree,item) ? ? ? ? ? ? ? ? }) ? ? ? ? ? ? } ? ? ? ? }, ? ? ? ? //將原數(shù)據(jù)tree對(duì)應(yīng)id的項(xiàng)的check值改為false ? ? ? ? updateParentCheck(tree,plistItem){ ? ? ? ? ? ? //console.log("方法updateParentCheck接收的plistItem參數(shù):",plistItem) ? ? ? ? ? ? tree.forEach(item=>{ ? ? ? ? ? ? ? ? if(item.id==plistItem.id){ ? ? ? ? ? ? ? ? ? ? item.check=false; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? if(item.id!==plistItem.id && item.children){ ? ? ? ? ? ? ? ? ? ? this.updateParentCheck(item.children,plistItem) ? ? ? ? ? ? ? ? } ? ? ? ? ? ? }) ? ? ? ? }, ? ? ? ? //子節(jié)點(diǎn)全部選中后父節(jié)點(diǎn)選中 ? ? ? ? childAllToParent(node,flatTree,j){ ? ? ? ? ? ? let fatherNode=''; ? ? ? ? ? ? let brotherNode=[]; ? ? ? ? ? ? this.flatTree.forEach(item=>{ ? ? ? ? ? ? ? ? if(node.pid && node.pid==item.id){ ? ? ? ? ? ? ? ? ? ? fatherNode=item;//找到了父節(jié)點(diǎn)--用于改變check的值 ? ? ? ? ? ? ? ? } ? ? ? ? ? ? }) ? ? ? ? ? ? //判斷該結(jié)點(diǎn)所有的兄弟節(jié)點(diǎn)是否全部選中 ? ? ? ? ? ? flatTree.forEach(item=>{ ? ? ? ? ? ? ? ? if(item.pid && node.pid && item.pid==node.pid){ ? ? ? ? ? ? ? ? ? ? brotherNode.push(item)//找到所有的兄弟節(jié)點(diǎn) ? ? ? ? ? ? ? ? } ? ? ? ? ? ? }) ? ? ? ? ? ? //i為被選中的兄弟節(jié)點(diǎn)的個(gè)數(shù) ? ? ? ? ? ? let i=0; ? ? ? ? ? ? this.flatTree.forEach(item=>{ ? ? ? ? ? ? ? ? if(node.pid==item.pid && item.check==true){ ? ? ? ? ? ? ? ? ? ? i=i+1; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? }) ? ? ? ? ? ? //修改父節(jié)點(diǎn)的選中值 ? ? ? ? ? ? if(i==brotherNode.length && fatherNode){ ? ? ? ? ? ? ? ? fatherNode.check=true ? ? ? ? ? ? } ? ? ? ? ? ? // console.log(`第j次遞歸 j=${j}`) ? ? ? ? ? ? // console.log(`選中的bro=${i},brother的個(gè)數(shù):${brotherNode.length}`) ? ? ? ? ? ? // console.log("父節(jié)點(diǎn):",fatherNode,"兄弟節(jié)點(diǎn)",brotherNode) ? ? ? ? ? ? if(fatherNode.pid!==undefined){ ? ? ? ? ? ? ? ? j=j+1; ? ? ? ? ? ? ? ? this.childAllToParent(fatherNode,this.flatTree,j) ? ? ? ? ? ? } ? ? ? ? } ? ? }, ? ? mounted(){ ? ? ? ? this.transformData(this.tree);//數(shù)據(jù)初始化:將tree樹形數(shù)據(jù)轉(zhuǎn)換為平行數(shù)據(jù) ? ? ? ? //console.log(this.flatTree) ? ? } } </script>
<style lang = "scss" scoped> .loginModuel{ ? ? margin-left: 400px; ? ? margin-top: 100px; ? ? .tree{ ? ? ? ? .ul{ ? ? ? ? ? ? >li{ ? ? ? ? ? ? ? ? margin: 5px 0 5px 0; ? ? ? ? ? ? ? ? >img{ ? ? ? ? ? ? ? ? ? ? position: relative; ? ? ? ? ? ? ? ? ? ? top: 2.4px; ? ? ? ? ? ? ? ? ? ? left: 4px; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? ? ? .ul2{ ? ? ? ? ? ? ? ? >li{ ? ? ? ? ? ? ? ? ? ? position: relative; ? ? ? ? ? ? ? ? ? ? left: 20px; ? ? ? ? ? ? ? ? ? ? margin: 5px 0 5px 0; ? ? ? ? ? ? ? ? ? ? >img{ ? ? ? ? ? ? ? ? ? ? ? ? //transition: all ease-in-out 1s; ? ? ? ? ? ? ? ? ? ? ? ? position: relative; ? ? ? ? ? ? ? ? ? ? ? ? top: 2.4px; ? ? ? ? ? ? ? ? ? ? ? ? left: 4px; ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? } ? ? } } input[type=checkbox]{ ? ? cursor: pointer; ? ? position: relative; ? ? width: 15px; ? ? height: 15px; ? ? font-size: 14px; ? ? border: 1px solid #dcdfe6; ? ? background-color: #fff !important; ? ? &::after{ ? ? ? ? position: absolute; ? ? ? ? top: 0; ? ? ? ? background-color: #fff; ? ? ? ? border: 1px solid #ddd; ? ? ? ? color: #000; ? ? ? ? width: 15px; ? ? ? ? height: 15px; ? ? ? ? display: inline-block; ? ? ? ? visibility: visible; ? ? ? ? padding-left: 0px; ? ? ? ? text-align: center; ? ? ? ? content: ' '; ? ? ? ? border-radius: 3px; ? ? ? ? transition: all linear .1s; ? ? } ? ? &:checked::after{ ? ? ? ? content: "?"; ? ? ? ? font-size: 12px; ? ? ? ? background-color: #409eff; ? ? ? ? border: 1px solid #409eff; ? ? ? ? transition: all linear .1s; ? ? ? ? color: #fff; ? ? ? ? font-weight: bold; ? ? } } </style>
子組件主要是實(shí)現(xiàn)全選和取消全選。由于遞歸組件的原因,子組件拿不到完整的數(shù)據(jù),所以接下來的兩個(gè)功能:全選后某一個(gè)子節(jié)點(diǎn)取消選中則父節(jié)點(diǎn)取消選中、子節(jié)點(diǎn)全選后父節(jié)點(diǎn)自覺選中的功能就要在父組件中完成了。
講解:
1、設(shè)值:
樹形數(shù)據(jù)必須有pid屬性,用于向上遍歷。
2、方法:
transformData():
將層級(jí)數(shù)據(jù)轉(zhuǎn)為平行數(shù)據(jù),避免后期不停的遞歸調(diào)用消耗時(shí)間,平級(jí)數(shù)據(jù)使用一般的循環(huán)即可完成。selectnode():
由子組件傳遞過來的方法,大致分為兩個(gè)方向:選中、取消選中。選中時(shí)實(shí)現(xiàn)功能一:子節(jié)點(diǎn)全選后父節(jié)點(diǎn)自覺選中;取消選中實(shí)現(xiàn)功能二:全選后某一個(gè)子節(jié)點(diǎn)取消選中則父節(jié)點(diǎn)取消選中。getParentnode():
用于實(shí)現(xiàn)功能二。子節(jié)點(diǎn)取消選中后,根據(jù)pid,將在它上面級(jí)別的所有父節(jié)點(diǎn)列表拿到,再由方法updateParentCheck()
將父節(jié)點(diǎn)的check
值全部改為false
。childAllToParent():
用于實(shí)現(xiàn)功能一。遞歸調(diào)用該方法,將操作節(jié)點(diǎn)的父節(jié)點(diǎn)拿到,根據(jù)兄弟節(jié)點(diǎn)有相同的pid,拿到兄弟節(jié)點(diǎn)的個(gè)數(shù),如果兄弟節(jié)點(diǎn)中被選中的個(gè)數(shù)等于兄弟節(jié)點(diǎn)的個(gè)數(shù),則修改父節(jié)點(diǎn)的check
值為true
,直到到了根節(jié)點(diǎn)結(jié)束遞歸。
- 這個(gè)組件實(shí)現(xiàn)起來不是很難,只要是心細(xì)就能很好的完成。
- 如果后期需要使用某些數(shù)據(jù)的話,直接掛到data里就可以。
- 如果有更好的方法或者存在某些疑問,歡迎小伙伴留言!
附: (global.js => 放于component文件夾下)
import Vue from 'vue'; function capitalizeFirstLetter(string){ ? ? return string.charAt(0).toUpperCase() + string.slice(1); } const requireComponent = require.context( ? ? '.',true,/\.vue$/ ? ? //找到components文件夾下以.vue命名的文件 ) requireComponent.keys().forEach(fileName => { ? ? const componetConfig = requireComponent(fileName); ? ? let a = fileName.lastIndexOf('/'); ? ? fileName = '.' + fileName.slice(a); ? ? const componetName = capitalizeFirstLetter( ? ? ? ? fileName.replace(/^\.\//,'').replace(/\.\w+$/,'') ? ? ) ? ? Vue.component(componetName,componetConfig.default || componetConfig) })
- 由此其實(shí)可以實(shí)現(xiàn)很多遞歸組件,如側(cè)邊欄。
- 下面我放一個(gè)自己寫的側(cè)邊欄的動(dòng)圖,方法比這個(gè)樹形組件要簡單些,畢竟不用考慮復(fù)選框的值。感興趣的小伙伴們可以試著實(shí)踐一下
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Vue組件庫ElementUI實(shí)現(xiàn)表格加載樹形數(shù)據(jù)教程
- Vue遞歸組件+Vuex開發(fā)樹形組件Tree--遞歸組件的簡單實(shí)現(xiàn)
- vue用遞歸組件寫樹形控件的實(shí)例代碼
- 用 Vue.js 遞歸組件實(shí)現(xiàn)可折疊的樹形菜單(demo)
- Vue.js遞歸組件構(gòu)建樹形菜單
- vuejs使用遞歸組件實(shí)現(xiàn)樹形目錄的方法
- 基于 Vue 的樹形選擇組件的示例代碼
- Vue組件模板形式實(shí)現(xiàn)對(duì)象數(shù)組數(shù)據(jù)循環(huán)為樹形結(jié)構(gòu)(實(shí)例代碼)
- Vue組件tree實(shí)現(xiàn)樹形菜單
- vue實(shí)現(xiàn)自定義樹形組件的示例代碼
相關(guān)文章
詳解win7 cmd執(zhí)行vue不是內(nèi)部命令的解決方法
這篇文章主要介紹了詳解win7 cmd執(zhí)行vue不是內(nèi)部命令的解決方法的相關(guān)資料,這里提供了解決問題的詳細(xì)步驟,具有一定的參考價(jià)值,需要的朋友可以參考下2017-07-07vue中的事件觸發(fā)(emit)及監(jiān)聽(on)問題
這篇文章主要介紹了vue中的事件觸發(fā)(emit)及監(jiān)聽(on)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10vue修改對(duì)象的屬性值后頁面不重新渲染的實(shí)例
今天小編就為大家分享一篇vue修改對(duì)象的屬性值后頁面不重新渲染的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-08-08關(guān)于vue-admin-element中的動(dòng)態(tài)加載路由
這篇文章主要介紹了關(guān)于vue-admin-element的動(dòng)態(tài)加載路由,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08在Vue項(xiàng)目中用fullcalendar制作日程表的示例代碼
這篇文章主要介紹了在Vue項(xiàng)目中用fullcalendar制作日程表,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08unplugin-auto-import的配置以及eslint報(bào)錯(cuò)解決詳解
unplugin-auto-import?解決了vue3-hook、vue-router、useVue等多個(gè)插件的自動(dòng)導(dǎo)入,也支持自定義插件的自動(dòng)導(dǎo)入,是一個(gè)功能強(qiáng)大的typescript支持工具,這篇文章主要給大家介紹了關(guān)于unplugin-auto-import的配置以及eslint報(bào)錯(cuò)解決的相關(guān)資料,需要的朋友可以參考下2022-08-08