Vue樹形結構操作
阿新 • • 發佈:2019-02-05
樹形結構是一種常用的資料結構,使用Vue怎麼來渲染呢?要把樹結構的每一個節點都渲染成dom,需要對樹結構進行遞迴遍歷。Vue元件可以通過name選項的設定來遞迴的呼叫自己,因此渲染起來很方便。
本文簡單實現了一下樹結構的基本增刪改等操作,實現效果可以在 http://wintc.top 檢視,後續還會繼續對樹結構渲染(比如拖拽操作、大資料量渲染效率等)進行探索。
程式碼比較簡單,MyTree元件:
<template> <div class="my-tree"> <div class="brother" v-for="(data, idx) of treeData" :key="idx"> <div class="node"> <span @click="data.expand=!data.expand"> <Button class="node-expand" type="text" icon="chevron-down" v-if="data.expand"></Button> <Button class="node-expand" type="text" icon="chevron-right" v-else></Button> </span> <input class="node-name" v-model="data.name" /> <span class="node-menu"> <span class="menu-item" title="新增同級節點" @click.stop="$emit('addBrother', $event, data)"> <Icon type="plus-round"></Icon> </span> <span class="menu-item" title="新增下級節點" @click.stop="$emit('addChild', $event, data)"> <Icon type="ios-plus-outline"></Icon> </span> <span class="menu-item" title=“刪除” @click.stop="$emit('deleteNode', $event, data)"> <Icon type="trash-a"></Icon> </span> </span> </div> <div class="children" v-if="data.children && data.children.length" v-show="data.expand"> <my-tree @addBrother="addBrother" @addChild="addChild" @deleteNode="deleteNode" :treeData="data.children"> </my-tree> </div> </div> </div> </template> <script> export default { name: 'my-tree', props: { treeData: { type: Array, default: () => [{ id: 1, name: '一級節點1', expand: true, children: [{ id: 2, expand: true, name: '二級節點1' }] }, { id: 3, expand: true, name: '一級節點2', children: [{ id: 4, expand: true, name: '二級節點1' }, { id: 5, expand: true, name: '二級節點2', children: [{ id: 6, expand: true, name: '三級節點' }] }] }] } }, methods: { addBrother (event, data) { this.$emit('addBrother', event, data) }, addChild (event, data) { this.$emit('addChild', event, data) }, deleteNode (event, data) { this.$emit('deleteNode', event, data) } } } </script> <style lang="stylus" scoped> .children position relative padding-left 20px .node-expand width 1.5rem height 1.5rem padding-left 0 padding-right 0 padding-bottom 0 padding-top 0 &:focus box-shadow none .node-menu width 3rem display flex justify-content space-around .menu-item &:hover cursor pointer .brother display flex flex-direction column .node height 1.5rem display flex align-items center .node-name // border none // background none overflow-x visible &:focus outline none </style>
元件使用,Tree.vue頁面程式碼:
<template> <div class="tree"> <div class="tree-title"> 樹結構 </div> <my-tree @addBrother="addBrother" @addChild="addChild" @deleteNode="deleteNode"> </my-tree> </div> </template> <script> import MyTree from '@/components/MyTree' export default { name: 'tree', components: { 'my-tree': MyTree }, data () { return { id: 100 } }, methods: { addBrother (event, data) { let parentData = this.getParentData(event.target) console.log(parentData) if (parentData) { let index = parentData.indexOf(data) if (index !== -1) { parentData.splice(index + 1, 0, this.newNode()) } } }, addChild (event, data) { if (!data.children) { this.$set(data, 'children', []) } data.children.push(this.newNode()) }, deleteNode (event, data) { let parentData = this.getParentData(event.target) if (parentData) { let index = parentData.indexOf(data) if (index !== -1) { parentData.splice(index, 1) } } }, newNode () { let id = this.id++ return { id, name: '新節點' + id, expand: true, children: [] } }, getParentData (node) { while (node && node.tagName !== 'BODY') { if (node.__vue__ && node.__vue__.$options.name === 'my-tree') { return node.__vue__.treeData } node = node.parentNode } return null } } } </script> <style lang="stylus" scoped> .tree padding 3rem 2rem text-align left .tree-title border-bottom 1px solid gray padding-bottom 0.5rem margin-bottom 1rem </style>
這裡使用了一些iView的圖示標籤,可以簡單的使用iView來實現漂亮的效果,可以到其iView官網瞭解使用方法。
學習前端也幾個月了,在開始使用Vue的很長一段時間裡,對Vue一些選項的作用不甚瞭解,在Vue官網都有比較清楚的介紹,比如遞迴渲染用到的name屬性:
-
型別:
string
-
限制:只有作為元件選項時起作用。
-
詳細:
允許元件模板遞迴地呼叫自身。注意,元件在全域性用
Vue.component()
註冊時,全域性 ID 自動作為元件的 name。
時常翻翻官網總會有意想不到的收穫~。~