之前写的,本来是以下拉列表展示,但是客户应要求以树的形式展示,百度了好久,没有找到合适的适合的树组件,最后只能自己上手了,展示效果如下:
- 组件treeNode.vue
<style>
.treeList {
line-height: 40px;
font-size: 14px;
overflow: hidden;
}
.parentTree {
position: relative;
}
.closeli {
position: absolute;
right: 10px;
top: 0;
}
.treeList .mui-icon-checkmarkempty {
color: #3498fe;
font-size: 30px;
}
</style>
<template>
<li class="treeList">
<div :style="style">
<div class="parentTree">
<span @click="nodeClick(node)">{{node.entityTitle}}</span>
<span class="mui-icon" :class="node.isChecked?'mui-icon-checkmarkempty':''"></span>
<div v-if="node.children && node.children.length > 0" class="closeli">
<span @click="changeStatus(node)" class="mui-icon" :class="node.close?'mui-icon-arrowdown':'mui-icon-arrowup'"></span>
<!-- <i @click="changeStatus(node)" v-else>折叠</i> -->
</div>
</div>
</div>
<tree-node @push="push" @remove="remove" v-show="!node.close" :level="level+2" :ref="'children'+index" :key="index" v-for="(item,index) in node.children" :node="item"></tree-node>
</li>
</template>
<script>
import linq from 'linq'
export default {
data: function () {
return {
style: {
paddingLeft: '',
borderBottom: '1px solid #dedede'
},
vals: []
}
},
props: ['node', 'ids', 'level'],
methods: {
// 展开状态变更
changeStatus: function (node) {
if (node) {
if (node.close) {
node.close = false
} else {
node.close = true
}
}
},
// 递归设置子节点的状态
setChildrensRole: function (node, val) {
var that = this
if (node.children !== null && node.children.length > 0) {
node.children.forEach(function (item, index) {
item.isChecked = val
if (item.children !== null) {
that.setChildrensRole(item, val)
}
})
}
},
nodeClick: function (node) {
node.isChecked = !node.isChecked
this.setChildrensRole(node, node.isChecked)
},
removeItem: function (val) {
let index = linq.from(this.vals).indexOf(val)
this.vals = this.vals.splice(index, 1, 0)
console.log(this.vals)
},
push: function (val) {
this.$emit('push', val)
},
remove: function (val) {
console.log(val)
this.$emit('remove', val)
}
},
watch: {
node: function () {
this.$set(this.node, 'close', true)
this.$set(this.node, 'isChecked', false)
},
'node.isChecked': function (val) {
if (this.node.children && this.node.children.length === 0) {
if (val) {
this.$emit('push', { id: this.node.entityCode, text: this.node.entityTitle })
} else {
this.$emit('remove', { id: this.node.entityCode, text: this.node.entityTitle })
}
}
}
},
created: function () {
this.$set(this.node, 'close', true)
this.$set(this.node, 'isChecked', false)
if (!this.level) {
this.level = 0
}
this.style.paddingLeft = (this.level * 10) + 'px'
},
components: {
TreeNode: resolve => require(['./treeNode.vue'], resolve)
}
}
</script>
2.组件tree.vue
<template>
<div style="overflow-y:auto">
<ul style="padding-left:5px" class="tree">
<tree-node :level="0" @push="push" @remove="remove" :ids="ids" v-for="(item,index) in datas" :key="index" :node="item"></tree-node>
</ul>
</div>
</template>
<script>
import linq from 'linq'
export default {
data () {
return {
ids: this.value,
datas: [],
labels: []
}
},
props: ['nodes', 'value', 'isNeedChangData'],
components: {
TreeNode: resolve => require(['./treeNode.vue'], resolve)
},
watch: {
nodes: function (val) {
this.datas = this.GetData(0, val)
}
},
created () {
this.datas = this.GetData(0, this.nodes)
},
methods: {
GetData: function (id, arry = this.nodes) {
let [vm, list] = [this, []]
var childArry = this.GetParentArry(id, arry)
if (childArry.length > 0) {
for (var i in childArry) {
let test = {
entityCode: childArry[i].entityCode,
entityTitle: childArry[i].entityTitle,
children: vm.GetData(childArry[i].entityId, arry)
}
list.push(test)
}
}
return list
},
GetParentArry: function (id, arry) {
var newArry = []
for (var i in arry) {
if (arry[i].parentId === id) {
newArry.push(arry[i])
}
}
return newArry
},
push: function (val) {
if (linq.from(this.ids).indexOf(val.id) < 0) {
this.ids.push(val.id)
this.labels.push(val.text)
this.$emit('input', this.ids)
this.$emit('update:labels', this.labels)
}
},
remove: function (val) {
let index = linq.from(this.ids).indexOf(val.id)
if (index > -1) {
this.ids.splice(index, 1)
this.labels.splice(index, 1)
}
this.$emit('input', this.ids)
this.$emit('update:labels', this.labels)
}
}
}
</script>
<style v-once scoped>
ul.tree ul {
margin-left: 0;
}
ul.tree li {
margin: 0;
padding: 0;
line-height: 40px;
color: #222;
border-top-right-radius: 0px;
border-top-left-radius: 0px;
}
ul.tree .licheckbox {
float: left;
width: 20px;
}
.positions ul li:last-child {
border-bottom: none !important;
}
.positions {
border-right: 1px solid;
}
</style>
3.应用到页面
<tree v-model="ids" :labels.sync="orgSelectLabels" :nodes="ownerGroups"></tree>
:labels.sync="orgSelectLabels"用于回显到前面选中的展示
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。