Vue遞歸組件+Vuex開發(fā)樹形組件Tree--遞歸組件的簡單實(shí)現(xiàn)
寫在前面
首先,本篇文章所開發(fā)的組件并非一個(gè)已經(jīng)開源的上線組件,所以如果你急于需要一個(gè)插件來只做你的項(xiàng)目,那么并不能帶給你及時(shí)的幫助。這個(gè)組件的開發(fā)預(yù)計(jì)寫兩篇文章,一遍寫組件,一篇寫組件邏輯。這篇文章也是我自己開發(fā)的從無到有的過程,所以它可以為你提供一些Tree組件開發(fā)的思路,代碼寫到一定程度,不能完全依賴插件了,有時(shí)間可以看看插件源碼或者動(dòng)手去開發(fā),這樣真的能加深對技術(shù)的掌握程度。
開發(fā)過程
1.數(shù)據(jù)倉庫-Vuex
2.組件的循環(huán)創(chuàng)建-遞歸組件
需求決定了我的技術(shù)選型,項(xiàng)目需求是一個(gè)中國各級政府列表的選擇,后臺(tái)基于大數(shù)據(jù)去匯總各級政府網(wǎng)站的文章決策,然后交給前端去展示,左側(cè)顯示各級政府的Tree,右側(cè)顯示具體文章。因?yàn)檎當(dāng)?shù)據(jù)的不確定性,所以顯示政府的Tree的每一層級也是動(dòng)態(tài)獲取的,就比如北京市下級的海淀區(qū)政府在一小時(shí)前可能不存在某某政策文章,那么北京市節(jié)點(diǎn)的子節(jié)點(diǎn)中就不會(huì)包含海淀區(qū)這一子節(jié)點(diǎn),但是10分鐘前網(wǎng)站發(fā)布了一篇文章,那么就需要在北京市中添加海淀區(qū),為了良好的實(shí)時(shí)性效果,每一級的子節(jié)點(diǎn)都不固定。
因此 樹狀結(jié)構(gòu)的data是變化的而不是在初始化的時(shí)候就固定好 的,數(shù)據(jù)驅(qū)動(dòng)Dom的思想,data有多少層級,Dom就有多少層級,data不定,所以Dom也無法提前定義好層級,決定采用Vue的遞歸組件,組件遞歸自身實(shí)現(xiàn)無限制層級的渲染。需求中每一個(gè)節(jié)點(diǎn)的Tree都具有增刪改的功能,因?yàn)閐ata是單例的,全局維護(hù)著一個(gè)data數(shù)據(jù)源頭,增刪改也就是操作data第n個(gè)子節(jié)點(diǎn)的某個(gè)子元素,因此采用了Vuex作為一個(gè)data存放的倉庫( 這不是一個(gè)組件庫,只是一個(gè)項(xiàng)目的應(yīng)用 )。
項(xiàng)目的關(guān)鍵點(diǎn):
1.動(dòng)態(tài)加載子節(jié)點(diǎn),也就是說頁面加載的時(shí)候,根節(jié)點(diǎn)的 nodes 子節(jié)點(diǎn)數(shù)組可能是個(gè)空數(shù)組,每次單擊節(jié)點(diǎn)去獲取子節(jié)點(diǎn)數(shù)組。
2.全局單例的樹節(jié)點(diǎn)對象 data 對象,每次得到新的子節(jié)點(diǎn),需要去維護(hù)這個(gè)對象,因?yàn)閿?shù)據(jù)與dom動(dòng)態(tài)綁定,所以每次數(shù)據(jù)對象內(nèi)部發(fā)生了變化,dom也會(huì)重繪。
vue對虛擬dom的映射通過使用diff算法進(jìn)行了優(yōu)化,所以不用擔(dān)心,重繪造成頁面閃屏
樹 data 數(shù)據(jù)結(jié)構(gòu)如下:
let data = { id: "01", lable: "政府機(jī)構(gòu)", nodes: [ { id: "02", lable: "中央機(jī)關(guān)", nodes: [{ //.. }] }, { id: "03", lable: "直轄市", nodes: [{ //.. //北京市... //天津市.. }] }, ] };
顯示成這樣:
每一個(gè)節(jié)點(diǎn)包含id,label,nodes三個(gè)屬性,nodes往下延伸子節(jié)點(diǎn),一共有多少級不確定根據(jù)后臺(tái)獲取得到。
遞歸組件
一個(gè)簡單的遞歸組件的示例如下:
<template> <div class="tree-menu"> //組件內(nèi)部不斷用自身,只要子節(jié)點(diǎn)存在就遞歸調(diào)用 <tree-menu v-for='(item, index) of dataNodes' :key='index'></tree-menu> </div> </template> <script> export default { name:'TreeMenu',//組件名稱必須寫 data() { return { dataNodes: { //... } } } } </script>
TreeMenu.vue聲明組件TreeMenu,并向外暴露,在組件內(nèi)部調(diào)用自身,也就是一個(gè)遞歸的思想,綁定的dataNodes有多少層級,那就會(huì)遞歸多少層,因?yàn)槊恳粚佣加衯-for都會(huì)循環(huán)子節(jié)點(diǎn)。綁定具體數(shù)據(jù)的時(shí)候再具體分析。不斷調(diào)用自身,當(dāng)然這只是一個(gè)例子,實(shí)際情況還要改造一下:
新建TreeMenu.vue,作為顯示節(jié)點(diǎn)的邏輯組件:
<template> <div class="tree-menu"> <div>{{label}}</div>//節(jié)點(diǎn)名稱 <tree-menu //如果nodes.length>0就遞歸顯示子節(jié)點(diǎn) v-for="(node, index) of nodes" :key="index" :nodes="node.nodes" //子節(jié)點(diǎn)的子節(jié)點(diǎn)向下傳遞 :label="node.label" > </tree-menu> </div> </template> <script> export default { name: "TreeMenu", props:['label','nodes'],//數(shù)據(jù)通過pros向下傳遞,全局唯一數(shù)據(jù)源 data() { return {}; } }; </script>
創(chuàng)建Tree.vue作為節(jié)點(diǎn)樹的入口:
<template> <div class="tree-alone"> <tree-menu :label="tree.label" :nodes="tree.nodes"></tree-menu> </div> </template> <script> import TreeMenu from './TreeMenu.vue' export default { name: 'tree', data() { return { tree: { id: "01", lable: "總層級", nodes: [ { id: "02", label: "層級1", nodes: [{ label: '層級1-1' }] }, { id: "03", label: "層級2", nodes: [] }, ] }; } } }, components: { TreeMenu } } </script>
在Tree.vue入口組件里引入子組件TreeMenu.vue,并且向子組件傳遞數(shù)據(jù)label和nodes,這里data先預(yù)定義一個(gè)簡單的對象,后面會(huì)動(dòng)態(tài)獲取。
TreeMenu.vue作為樹形菜單組件,負(fù)責(zé)遞歸和數(shù)據(jù)渲染,它會(huì)接受來自入口組件傳遞來的label和nodes數(shù)據(jù),進(jìn)行渲染, 并且繼續(xù)遞歸傳遞nodes和label 。
在從父組件接收nodes和label后,先循環(huán)渲染n個(gè)tree-menu組件,然后每一個(gè)tree-menu又會(huì)遞歸自身,所以數(shù)據(jù)就這樣一層層向下傳遞nodes=>nodes.node=>nodes.node.node,此時(shí)已經(jīng)完成了數(shù)據(jù)與Dom的綁定,可以修改一下Tree.vue中的tree數(shù)據(jù)源,看一下組件是否動(dòng)態(tài)改變了?,F(xiàn)在渲染如下圖:
數(shù)據(jù)正確渲染,現(xiàn)在需要加一些樣式和點(diǎn)擊事件(展開與收縮),就不做詳細(xì)介紹了,代碼如下: (向下傳遞depth參數(shù)來獲取層級索引)
//Tree.vue <template> <div class="tree-alone"> <tree-menu :label="tree.label" :nodes="tree.nodes" :depth="0"></tree-menu> </div> </template> //TreeMenu.vue <template> <div class="tree-menu"> <div :style="indent" @click="toggleChildren">{{label}}</div> <div v-if="showChildren"> <tree-menu v-for="(item, index) of nodes" :key="index" :nodes="node.nodes" :label="node.label" :depth="depth + 1" ></tree-menu> </div> </div> </template> <script> export default { name: "TreeMenu", props: ["label", "nodes"], data() { return { showChildren: false }; }, methods: { toggleChildren() { this.showChildren = !this.showChildren; } }, computed: { indent() { return { transform: `translate(${this.depth * 20}px)` }; } } }; </script>
修改后會(huì)展開收縮與縮進(jìn),一些箭頭旋轉(zhuǎn)等樣式問題就不詳細(xì)寫了。
總結(jié)
以上所述是小編給大家介紹的Vue遞歸組件+Vuex開發(fā)樹形組件Tree--遞歸組件的簡單實(shí)現(xiàn),希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
- vue遞歸實(shí)現(xiàn)樹形組件
- Vue組件庫ElementUI實(shí)現(xiàn)表格加載樹形數(shù)據(jù)教程
- vue用遞歸組件寫樹形控件的實(shí)例代碼
- 用 Vue.js 遞歸組件實(shí)現(xiàn)可折疊的樹形菜單(demo)
- Vue.js遞歸組件構(gòu)建樹形菜單
- vuejs使用遞歸組件實(shí)現(xiàn)樹形目錄的方法
- 基于 Vue 的樹形選擇組件的示例代碼
- Vue組件模板形式實(shí)現(xiàn)對象數(shù)組數(shù)據(jù)循環(huán)為樹形結(jié)構(gòu)(實(shí)例代碼)
- Vue組件tree實(shí)現(xiàn)樹形菜單
- vue實(shí)現(xiàn)自定義樹形組件的示例代碼
相關(guān)文章
vue進(jìn)入頁面加載數(shù)據(jù)緩慢實(shí)現(xiàn)loading提示過程
這篇文章主要介紹了vue進(jìn)入頁面加載數(shù)據(jù)緩慢實(shí)現(xiàn)loading提示過程,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08Element-Plus的ClickOutside指令導(dǎo)致內(nèi)存泄漏的解決辦法
這篇文章給大家介紹了Element-Plus的ClickOutside指令導(dǎo)致內(nèi)存泄漏的解決辦法,文中給出了詳細(xì)的解決辦法,遇到同樣問題的小伙伴可以參考閱讀一下本文2024-01-01詳解vue-cli4 配置不同開發(fā)環(huán)境打包命令
這篇文章主要介紹了vue-cli4 配置不同開發(fā)環(huán)境打包命令,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07vue3動(dòng)態(tài)路由刷新出現(xiàn)空白頁的原因與最優(yōu)解
頁面刷新白屏其實(shí)是因?yàn)関uex引起的,由于刷新頁面vuex數(shù)據(jù)會(huì)丟失,這篇文章主要給大家介紹了關(guān)于vue3動(dòng)態(tài)路由刷新出現(xiàn)空白頁的原因與最優(yōu)解的相關(guān)資料,需要的朋友可以參考下2023-11-11vue實(shí)現(xiàn)滑塊拖拽校驗(yàn)功能的全過程
vue驗(yàn)證滑塊功能,在生活中很多地方都可以見到,使用起來非常方便,這篇文章主要給大家介紹了關(guān)于vue實(shí)現(xiàn)滑塊拖拽校驗(yàn)功能的相關(guān)資料,需要的朋友可以參考下2021-08-08