需求: vue实现仿zTree折叠树,此文章仅作为记录文档。

实现:

<template>
<div class="line-tree">
<div v-for="(item, index) in treeData" :key="index" class="single-content" :class="treeLine ? getSecond(item) : ''">
<span></span>
<p class="parent-node">
<!-- treeLine 是否显示连接线 -->
<span v-if="treeLine">
<span class="line-7" v-if="level !== 0 && (item.children && item.children.length)"></span>
<span class="line-25" v-if="level !== 0 && (!item.children || !item.children.length)"></span>
<span v-if="item.last" class="line-10-last"></span>
</span> <span v-if="item.children && item.children.length && item.name" class="arrow-icon" @click="changeState(item)">
<img src="../../../../static/images/jurisdiction-add.png" v-if="!item.expand" alt="+" class="expand-icon">
<img src="../../../../static/images/jurisdiction-cut.png" v-else alt="-" class="expand-icon">
</span>
<span v-else>
<i style="display: inline-block; height: 14px; width: 16px; position: relative; top: 2px;"></i>
</span>
<span v-if="keyTree == 'role'">
<span class="city" :class="{'active-name' : treeActive === item.id}" @click="item.children.length === 0 ? skipCost(item) : parentClick(item)">{{item.name}}</span>
</span>
<span v-else>
<span class="city" :class="{'active-name' : treeActive === item.id}" @click="(item.children.length === 0 || item.deep === 1) ? skipCost(item) : parentClick(item)">{{item.name}}</span>
</span>
</p> <div v-if="item.children && item.children.length && item.expand" class="sub-content" :class="treeLine ? cancelBor(item) : ''">
<permission-base-tree @skipCost="skipCost" :currentDep="currentDep" :level="level + 1" :treeData="item.children" :keyTree="keyTree"></permission-base-tree>
</div>
</div>
</div>
</template>
<script>
import { mapGetters, mapMutations } from "vuex";
export default {
name: 'permission-base-tree',
data() {
return {}
},
props: {
treeData: {
type: Array,
default: () => []
},
level: {
type: Number,
default: () => 0
},
currentDep: {
type: Number,
default: () => 0
},
keyTree: {
type: String,
default: () => ""
},
treeLine: {
type: Boolean,
default: () => false
}
},
computed: {
...mapGetters(["treeActive"])
},
watch: {
treeData: {
handler(newVal, oldVal) {
if (newVal) {
this.treeData = newVal;
}
},
deep:true
},
},
created() {
},
methods: {
...mapMutations({
setActive: 'SET_treeActive'
}),
skipCost(item) {
this.setActive(item.id);
this.$emit('skipCost', item);
},
parentClick(item) {
this.setActive(item.id);
item.expand = !item.expand;
}, /**
* 改变生效状态
*/
changeEffect(item, sub) {
this.$emit('changeEffect', [item, sub]);
},
/**
* 添加
*/
add(item) {
console.log('item', item);
this.$emit('add', item);
},
/**
* 编辑
*/
edit(item, sub) {
this.$emit('edit', [item, sub]);
},
/**
* 删除
*/
deleteWarning(item, sub) {
this.$emit('deleteWarning', [item, sub]);
},
changeSelect(item, index){
item.select = !item.select;
if (item.select) { // 子类全选
if (item.children && item.children.length) {
// 子类变为选中状态
this.transferTrue(item.children, true);
}
console.log('select',[true, item.levelList]);
this.$emit('changeParent', [true, item.levelList]);
} else { // 取消全选
if (item.children && item.children.length) {
this.transferTrue(item.children, false);
}
this.$emit('changeParent', [false, item.levelList]);
}
},
changeParent(val) {
if (val[0]) { // 子类为true
let flag = true;
let arr = val[1].slice(0, val[1].length - 1);
let idx = arr[arr.length - 1];
for (let i = 0; i < this.treeData[idx].children.length; i++) {
if (!this.treeData[idx].children[i].select) {
flag = false;
break;
}
}
if (flag) {
this.treeData[idx].select = true;
} else {
this.treeData[idx].select = false;
}
this.$emit('changeParent', [true, this.treeData[idx].levelList])
} else {
let arr = val[1].slice(0, val[1].length - 1);
let idx = arr[arr.length - 1];
this.treeData[idx].select = false;
this.$emit('changeParent', [false, this.treeData[idx].levelList],val[2]);
}
},
cancelBor(item) {
if (!item.last) {
return 'add-second';
}
},
getSecond(item) {
if (!item.last) {
return 'add-second';
}
}, getMargin(item) {
let currentLevel = item.level;
if (item.children && item.children.length) {
return {
marginRight: (this.currentDep - item.level - 1) * 18 + 'px'
}
}
},
transferTrue(arr, flag) {
arr.forEach((item, index) => {
item.select = flag;
if (item.children && item.children.length) {
this.transferTrue(item.children, flag);
}
})
},
changeState(item) {
item.expand = !item.expand;
}
}
}
</script>
<style lang="less" scoped>
.line-tree {
font-size: #000;
.single-content {
position: relative;
left: -11px;
padding-left: 11px;
}
.single-troditional {
display: inline-block;
height: 24px;
line-height: 24px;
background: #B1D6FF;
margin-right: 10px;
padding: 0 5px;
color: #000;
border-radius: 3px;
}
.common-img {
display: inline-block;
margin-left: 5px;
}
.common-img:hover {
cursor: pointer;
}
.add-continal {
color: #0847A9;
margin-right: 15px;
}
.add-continal:hover {
cursor: pointer;
}
.add-second {
border-left: 1px dashed #FFF;
}
.line-15 {
position: absolute;
left: -10px;
top: 15px;
display: inline-block;
width: 1px;
height: 13px;
border-left: 1px dashed #FFF;
}
.line-10 {
position: absolute;
left: -10px;
top: 0;
display: inline-block;
width: 1px;
height: 15px;
border-left: 1px dashed #FFF;
}
.line-10-last {
position: absolute;
left: -11px;
top: 0;
display: inline-block;
width: 1px;
height: 15px;
border-left: 1px dashed #FFF;
}
.line-7 {
position: absolute;
left: -10px;
top: 15px;
display: inline-block;
width: 7px;
height: 1px;
border-bottom: 1px dashed #FFF;
}
.line-25 {
position: absolute;
left: -10px;
top: 15px;
display: inline-block;
width: 25px;
height: 1px;
border-bottom: 1px dashed #FFF;
}
.sub-content {
margin-left: 7px;
padding-left: 11px;
}
.add-border {
border-left: 1px dashed #FFF;
}
.parent-node {
height: 30px;
vertical-align: middle;
position: relative;
white-space: nowrap;
}
img {
vertical-align: middle;
}
.file-icon {
display: inline-block;
width: auto;
height: 14px;
}
.arrow:hover {
cursor: pointer;
}
.select-icon {
display: inline-block;
width: 15px;
height: 15px;
}
.last-content {
padding-left: 30px;
}
.select-box:hover {
cursor: pointer;
}
.city {
font-size: 14px;
color: #000;
display: inline-block;
height: 30px;
line-height: 30px;
}
.active-name {
color: #0847A9;
font-weight: bold;
text-decoration: underline;
}
.city:hover {
cursor: pointer;
}
.expand-icon {
display: inline-block;
height: 14px;
width: auto;
}
.expand-icon:hover {
cursor: pointer;
}
.init-line {
position: absolute;
left: 7px;
top: -3px;
display: inline-block;
width: 0;
height: 8px;
box-sizing: border-box;
border-left: 1px dashed #FFF;
}
.outer {
position: absolute;
left: 7px;
top: 2px;
display: inline-block;
width: 14px;
height: 20px;
box-sizing: border-box;
border-left: 1px dashed #FFF;
.inner {
display: inline-block;
width: 10px;
height: 0;
box-sizing: border-box;
border-bottom: 1px dashed #FFF;
position: relative;
top: 0px;
}
} .outer-sub {
position: absolute;
left: 7px;
display: inline-block;
width: 14px;
height: 13px;
top: 2px;
box-sizing: border-box;
border-left: 1px dashed #FFF;
.inner-sub {
display: inline-block;
width: 10px;
height: 0;
box-sizing: border-box;
border-bottom: 1px dashed #FFF;
position: relative;
top: 0px;
}
}
}
</style>

最新文章

  1. SQL Server 2008 R2没有卸载干净
  2. dic+css页面布局分享
  3. linux 目录结构图解
  4. 04 SQL是关于集合的
  5. SID与GUID的区别
  6. php的异步框架
  7. 【原创】alias与export
  8. NOIP2001 Car的旅行路线
  9. 【二分答案】【POJ3122】【Northwestern Europe 2006】Pie
  10. object-c中的BOOL类型
  11. spark使用总结
  12. Oracle12c多租户管理用户、角色、权限
  13. Xdebug的优点!php代码开发
  14. C#学习笔记-DataTable导出到EXCEL(一)
  15. Ehcache 3.7文档—基础篇—JCache aka JSR-107
  16. Container&amp;injection
  17. Servlet执行流程和生命周期
  18. poj2442 堆应用
  19. Spring boot FastJson
  20. 笔记:Oracle查询重复数据并删除,只保留一条记录

热门文章

  1. Linux下的C语言编程
  2. HDU 3920 Clear All of Them I(状压DP)题解
  3. element-ui &amp; babel-plugin-component config bug
  4. GraphQL All In One
  5. Vue Big Changes All in One
  6. 来必力 &amp; Disqus
  7. taro error
  8. Flutter 使用高德地图定位
  9. js jsonParse
  10. eclipse中将项目加载到tocat报错:Tomcat version 6.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5 Web modules