Vue树形结构操作
树形结构是一种常用的数据结构,使用Vue怎么来渲染呢?要把树结构的每一个节点都渲染成dom,需要对树结构进行递归遍历。Vue组件可以通过name选项的设置来递归的调用自己,因此渲染起来很方便。本文简单实现了一下树结构的基本增删改等操作,后续还会继续对树结构渲染(比如拖拽操作、大数据量渲染效率等)进行探索。代码比较简单,MyTree组件:<te...
·
树形结构是一种常用的数据结构,使用Vue怎么来渲染呢?要把树结构的每一个节点都渲染成dom,需要对树结构进行递归遍历。Vue组件可以通过name选项的设置来递归的调用自己,因此渲染起来很方便。
本文简单实现了一下树结构的基本增删改等操作,后续还会继续对树结构渲染(比如拖拽操作、大数据量渲染效率等)进行探索。
代码比较简单,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。
时常翻翻官网总会有意想不到的收获~。~
更多推荐
已为社区贡献4条内容
所有评论(0)