vue实现的树形结构加多选框⽰例
本⽂实例讲述了vue实现的树形结构加多选框。分享给⼤家供⼤家参考,具体如下:
前⾯说了如何⽤递归组件来写vue树形结构,写了树形结构还要在前⾯加多选框,然后往数组⾥push选项,并在左边显⽰出来,然后左边进⾏拖拽排序,拖拽排序上⼀篇⽂章我已经介绍过了,在这我就不介绍了,如何⽤阿⾥巴巴⽮量图标库我也有相关⽂章,也不介绍了,本节主要介绍vue树形结构加多选框,并实现⼀定的逻辑,⽐如全选,单选,全选和单选之间的联动
先看下⽬录结构
下⾯我直接贴下代码
⾸先是pages⽂件夹中tree.vue页⾯中引⽤组件
下⾯是tree.vue的代码
<template>
<div class = "loginModuel">
<Tree :menus = "menus" :depth = "depth" @selectItem = "selectItem" :actId = "actId" @checkItem = "checkItem"></Tree>
</div>
</template>
<script src = "./index.js"></script>
<style lang = "scss" scoped src = "./index.scss"></style>
然后是tree.vue引⼊的index.js的代码
import Tree from '../../components/tree/tree';
import axios from 'axios';
export default{
data(){
return{
msg:"这是登录页⾯",
depth:0,
menus:[],
actId:"",
}
},
components:{
Tree
},
methods:{
//⽤ajax获取数据
getData(){
('/static/json/data.json');
},
// 调⽤ajax函数
async getTree(){
var last = Data();
if(de == 1){
//在每⼀项中添加selectArr和show
this.us);
}
},
//递归函数在每⼀项中添加selectArr和show
addShow(arr){
for(var i = 0; i < arr.length;i++){
this.$set(arr[i],"show",true);
this.$set(arr[i],"selectArr",[]);
if(arr[i].userList && arr[i].userList.length > 0){
this.addShow(arr[i].userList)
}
}
},
/
/点击箭头使树展开收缩
selectItem(data){
if(data.userList && data.userList.length > 0){
//如果此项下有userList且length⼤于0,则切换展开与折叠状态
data.show = !data.show;
}else{
//如果此项下没有userList或length等于0,则将选中的id赋值给actId
this.actId = data.id;
}
},
//进⾏多选勾选
checkItem(data){
if(data.selectArr.length > 0){
//如果这⼀项的selectArr有值,说明是被勾选状态,要把selectArr清空,清空勾选
data.selectArr = [];
//如果此选项清空勾选后,如果下⾯有userList的话,那么也同时要清空
if(data.userList && data.userList.length > 0){
this.clearChild(data.userList);
}
//如果此选项清空勾选后,要把所有的⽗元素,也全部清空勾选,因为它不勾选了,所有⽗元素的状态不可能还处于勾选状态,不管它勾选不勾选,我们都要清除⼀遍,以防万⼀ajax实例里面的函数
this.us,data);
}else{//如果这⼀项的selectArr为[],说明是未被勾选状态,在selectArr⾥加id值,添加勾选
data.selectArr.push(data.id);
//如果此选项清空勾选后,如果下⾯有userList的话,那么也同时勾选下⾯所有的孩⼦
if(data.userList && data.userList.length > 0){
this.addChild(data.userList);
}
//如果此选项勾选后,要判断所有的上级元素是不是应该全部打勾
this.us,data);
}
clearChild(arr){
for(var i = 0; i < arr.length;i++){
arr[i].selectArr = [];
if(arr[i].userList && arr[i].userList.length > 0){
this.clearChild(arr[i].userList);
}
}
},
//定义函数添加所有孩⼦的勾选
addChild(arr){
for(var i = 0; i < arr.length;i++){
arr[i].selectArr.push(arr[i].id);
if(arr[i].userList && arr[i].userList.length > 0){
this.addChild(arr[i].userList);
}
}
},
//定义函数⼀层⼀层的往上寻⽗元素的userList
clearFather(father,data){
for(var i = 0; i < father.length;i++){
if(father[i].id == data.id){
//到data所在的userList为father,然后再通过这个userList到拥有这个userList的⽗元素
this.us,father);
}else if(father[i].userList && father[i].userList.length > 0){
this.clearFather(father[i].userList,data);
}
}
},
//定义函数根据到的上层⽗元素的userList来寻⽗元素,并将他们清除勾选
clearRealFather(menus,arr){
for(var i = 0; i < menus.length;i++){
if(menus[i].userList == arr){
//到这个拥有userList的⽗元素后,将此selectArr清空
menus[i].selectArr = [];
//到这个拥有userList的⽗元素后,再调⽤clearFather,再进⾏向上寻⽗元素,知道没有⽗元素为⽌
this.us,menus[i]);
}else if(menus[i].userList && menus[i].userList.length > 0){
this.clearRealFather(menus[i].userList,arr);
}
}
},
//定义函数⼀层⼀层的往上寻⽗元素的userList
selectFather(father,data){
for(var i = 0; i < father.length;i++){
if(father[i].id == data.id){
var arr = [];
for(var j = 0; j < father.length;j++){
if(father[j].selectArr.length > 0){
arr.push(father[i]);
}
}
//判断此数组中是不是所有的selectArr都有值,如果有值,就执⾏selectRealFather,将上层⽗元素也勾选
if(arr.length == father.length){
this.us,father);
}
}else if(father[i].userList && father[i].userList.length > 0){
this.selectFather(father[i].userList,data);
}
}
},
//定义函数根据到的上层⽗元素的userList来寻⽗元素,并将他们清除勾选
selectRealFather(menus,arr){
for(var i = 0; i < menus.length;i++){
if(menus[i].userList == arr){
//到这个拥有userList的⽗元素后,给selectArr赋值,使其勾选
menus[i].selectArr.push(menus[i].id);
//到这个拥有userList的⽗元素后,再调⽤clearFather,再进⾏向上寻⽗元素,知道没有⽗元素为⽌
this.us,menus[i]);
}else if(menus[i].userList && menus[i].userList.length > 0){
this.selectRealFather(menus[i].userList,arr);
}
}
}
},
mounted(){
}
}
然后是树形组件components⽂件夹中tree.vue的代码
<template>
<ul class = "treeMoudel">
<li v-for = "(item,index) in menus" :key = "index">
<!-- 遍历menus,如果传过来的depth等于0,就添加topNode的class,如果不等于0,就添加noTopNode的class -->
<div :class = "{'itemTree':true,'topNode':depth == 0,'noTopNode':depth != 0,'active':actId == item.id}">
<!-- 判断如果含有name字段就显⽰name字段 -->
<span :style = "transform" v-if = "item.name" :class = "{'topSpan':depth == 0,'noTopSpan':depth != 0}">
<!-- 如果item有孩⼦且item.show为false,那么图标为折叠图标 -->
<i class = "el-icon-caret-right" v-if = "item.userList && item.userList.length > 0 && !item.show" @click = "selectItem(item)"></i> <!-- 如果item有孩⼦且item.show为true,那么图标为展开图标 -->
<i class = "el-icon-caret-bottom" v-if = "item.userList && item.userList.length > 0 && item.show" @click
= "selectItem(item)"></i> <i class = "selectBox" @click = "checkItem(item)">
<!-- 如果item的selectArr.length是⼤于0的,也就是⾥⾯有值的话就是勾选状态,否则就是不勾选状态 -->
<i :class = "{'checkName iconfont':true, 'gouxuan5':item.selectArr.length > 0}" ></i>
</i>
{{item.name}}
<!-- 判断如果含有username字段就显⽰username字段 -->
<span :style = "transform" v-if = "item.username" :class = "{'topSpan':depth == 0,'noTopSpan':depth != 0}">
<!-- 如果item有孩⼦且item.show为false,那么图标为折叠图标 -->
<i class = "el-icon-caret-right" v-if = "item.userList && item.userList.length > 0 && !item.show" @click = "selectItem(item)"></i>
<!-- 如果item有孩⼦且item.show为true,那么图标为展开图标 -->
<i class = "el-icon-caret-bottom" v-if = "item.userList && item.userList.length > 0 && item.show" @click = "selectItem(item)"></i>
<i class = "selectBox" @click = "checkItem(item)">
<!-- 如果item的selectArr.length是⼤于0的,也就是⾥⾯有值的话就是勾选状态,否则就是不勾选状态 -->
<i :class = "{'checkUsername iconfont':true, 'gouxuan5':item.selectArr.length > 0}"></i>
</i>
{{item.username}}
</span>
</div>
<el-collapse-transition>
<!-- 递归组件就是⾃⼰调⽤⾃⼰,这⾥是在⾃⼰的组件内再次调⽤⾃⼰,但是务必要和pages中的tree页⾯中使⽤的⼀模⼀样才可以,否则树不会⽣效 -->
<Tree v-if = "item.userList && item.userList.length > 0 && item.show" :menus = "item.userList" :depth = "depth+4" @selectItem = "selectItem" :actId = "actId" @checkItem = "checkItem"></Tree> </el-collapse-transition>
</li>
</ul>
</template>
<script src = "./index.js"></script>
<style src = "./index.scss" lang = "scss" scoped></style>
export default{
name:"Tree",
props:["menus","depth","actId"],
data(){
return{
msg:"这是⼆级菜单树",
}
},
methods:{
// 将selectItem⽅法暴露出去
selectItem(item){
this.$emit("selectItem",item);
},
// 将checkItem⽅法暴露出去
checkItem(item){
this.$emit("checkItem",item);
}
},
computed:{
//通过传过来的depth计算下级⽬录的偏移量,这⾥我⽤的transform
transform(){
return 'transform:translateX(' + this.depth*10 + 'px)';
}
}
}
.treeMoudel{
li{
.itemTree{
width: 100%;
padding-left:30px;
position: relative;
&:hover{
background:#2B9EEE;
color:#fff;
}
.selectBox{
display: inline-block;
width: 16px;
height:16px;
border:1px solid #ccc;
border-radius: 3px;
position: relative;
background: #fff;
top:2px;
.
checkName{
position: absolute;
top:-16px;
left:0px;
color:#333;
}
.checkUsername{
position: absolute;
top:-12px;
left:0px;
color:#333;
}
}
span{
display: inline-block;
position: absolute;
font-size:14px;
}
.topSpan{
font-size:16px;
}
.noTopSpan{
font-size:14px;
}
}
.topNode{
line-height: 55px;
font-size:16px;
cursor: pointer;
}
.active{
background:#2B9EEE;
color:#fff;
}
.noTopNode{
height:45px;
line-height:45px;
&:hover{
background:#2B9EEE;
cursor: pointer;
color:#fff;
}
}
}
}
看⼀下模拟数据的data.json长什么样⼦吧
{
"code":1,
"data":[
{
"id":"1.2",
"name":"技术部",
"userList":[
{
"id":"788d",
"username":"html",
"role":"主管"
},
{
"id":"sda",
"username":"vue",
"role":"普通"
}
]
},
{
"id":"1.3",
"name":"策划部",
"userList":[
{
"id":"dsf",
"username":"jack",
"role":"主管"
},
{
"id":"asdf",
"username":"rose",
"role":"普通"
}
]
}
]
}
⾄此,⼀个树形组件加多选框就做好了
下⾯看下效果图
ok,⾃此这⼀功能就实现啦,代码讲解我就不写了,注释⾥写的清清楚楚的,看注释就好啦!希望本⽂所述对⼤家vue.js程序设计有所帮助。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论