可进行修改,此版本是父级关联子级,点击子级不需要选择父级的业务需求
完整关联的可在下面修改
treeList.vue
<template>
<div>
<my-trees :list="list" @getResult="getResult" ref="treeMenu"></my-trees>
</div>
</template>
<script>
let vue=this;
import myTrees from './treeMenus'
export default {
components: {
myTrees
},
props:{
data: {
type: Array,
required: true
},
props:{
type:Object
}
},
data () {
return {
// list: [//实例
// {
// name: '一级',checked:false,expendclick:false,id:'1',parentId:'0',
// cList: [
// { name: '二级一',checked:false,expendclick:false,id:'21',parentId:'1' },
// {
// name: '二级二',checked:false,expendclick:false,id:'22',parentId:'1',
// cList: [
// { name: '三级',checked:false,expendclick:false,id:'31',parentId:'22', cList: [{ id:'41',parentId:'31',name: '四级' ,checked:false,expendclick:false,}] }
// ]
// }
// ]
// },]
list:[],
isTreeRoot:true,//验证真实根组件
checkList:[],//选中值
checkData:[],//返回选择值
}
},
mounted(){
},
watch:{
data(n,o){ // 监听收到转换前数据
// handler:(n,o) => {
if(n){
this.list=this.ruleList(JSON.parse(JSON.stringify(n)))
}
},
},
methods: {
async getResult(val){//接收子元素的,修改父元素
await this.searchList(this.list,val)
await this.getChecked()
},
async searchList(arr,val){
await arr.map(item=>{
if(item.id==val){//不管子元素如何变化,只要是点击子元素就要把父级元素checked改为false
this.$set(item,'checked',false)
let code=item.cList.every(vall=>{
return vall.checked==false&&vall.indeterminate==false
})
if(!code){
this.$set(item,'indeterminate',true) //只要子级元素checked与indeterminate有true,则父级的indeterminate比为true
if(item.parentId){//只要有父级元素就进行上级递归
this.searchList(this.list,item.parentId)
}
}else{
this.$set(item,'indeterminate',false)//只要子级元素checked与indeterminate全部为false,则父级的indeterminate比为false
if(item.parentId){//只要有父级元素就进行上级递归
this.searchList(this.list,item.parentId)
}
}
// if(item.parentId&&item.parentId!=='0'){//没有父级时进行上级递归
// this.getResult(item.parentId)
// }
}else{
if(item.cList&&item.cList.length){
return this.searchList(item.cList,val) //下级递归
}
}
})
},
setCheckedKeys(arr){ //设置选中
let datas=JSON.parse(JSON.stringify(this.data))
this.list=this.ruleList(datas)
if(arr.length){
arr.map(item=>{
this.setcheckList(this.list,item[this.props.value])
})
}
},
setcheckList(arr,id){
arr.map(item=>{
if(item.id==id){
this.$set(item,'checked',true)
this.$refs.treeMenu.changValue(item)//将设置选中的值进行触发点击事件
}else{
if(item.cList&&item.cList.length){
this.setcheckList(item.cList,id)
}
}
})
},
async getChecked(){//获取选中元素并传递给父级组件
this.checkList=[]
this.checkData=[]
await this.searchCheck(this.list) // 获取转换后选中元素
this.checkList.map(item=>{
this.seaarchData(this.data,item.id) //获取转换前选中元素
})
this.$emit('check',this.checkData)//将转换前选中元素传递给父元素
},
searchCheck(arr){// 获取转换后选中元素
arr.map(item=>{
if(item.checked){
this.checkList.push(item)
}else{
if(item.cList&&item.cList.length){
return this.searchCheck(item.cList)
}
}
})
},
seaarchData(arr,id){//获取转换前选中元素
arr.map(item=>{
if(item[this.props.value]==id){
let ids=[]
if(this.checkData.length){
this.checkData.map(val=>{
return ids.push(val[this.props.value])
})
}
if(ids.indexOf(id)==-1){
this.checkData.push(item)
}
}else{
if(item[this.props.children]&&item[this.props.children].length){
return this.seaarchData(item[this.props.children],id)
}
}
})
},
ruleList(arr){//将接受到的值转换为需要样式
let arrs=arr.map(item=>{
// this.$set(item,"checked",false)
// this.$set(item,"expendclick",false)
item.checked=false
item.expendclick=false
item.indeterminate=false
if(this.props.label){//元素属性替换
let regExp = new RegExp(this.props.label, 'g');
item=JSON.parse(JSON.stringify(item).replace(regExp,"name"));
}
if(this.props.children){
let regExps = new RegExp(this.props.children, 'g');
item=JSON.parse(JSON.stringify(item).replace(regExps,"cList"));
}
if(this.props.value){
let regExpid = new RegExp(this.props.value, 'g');
item=JSON.parse(JSON.stringify(item).replace(regExpid,"id"));
}
if(this.props.parentId){
let regExpparentId=new RegExp(this.props.parentId, 'g');
item=JSON.parse(JSON.stringify(item).replace(regExpparentId,"parentId"));
}
if(this.props.disabled){
let regExpdisabled=new RegExp(this.props.disabled, 'g');
item=JSON.parse(JSON.stringify(item).replace(regExpdisabled,"disabled"));
}
if(item.cList&&item.cList.length){
item.cList=this.ruleList(item.cList)
}
return item
})
return arrs
}
}
}
</script>
treeMenus.vue
<template>
<ul class="treeList">
<li v-for="(item,index) in list" :key="index">
<p @click="changeStatus(index,item)" :class="{'spanColor':true,'el-icon-caret-right':(!item.expendclick&&item.cList),'el-icon-caret-bottom':(item.expendclick&&item.cList)}">
<span v-if="!(item.cList&&item.cList.length)" style="padding-left:13px;">
</span>
<!-- <el-checkbox v-model="item.checked" @change="changValue(item)" :disabled="item.disabled">
</el-checkbox> -->
<el-checkbox v-if="item.checked" v-model="item.checked" @change="changValue(item)" :disabled="item.disabled">
</el-checkbox>
<el-checkbox v-else :indeterminate="item.indeterminate" v-model="item.checked" @change="changValue(item)" :disabled="item.disabled"></el-checkbox>
{{item.name}}
</p>
<tree-menus v-if="scopesDefault[index]" :list="item.cList"></tree-menus>
</li>
</ul>
</template>
<style scoped lang="scss">
.treeList {
padding-left: 20px !important;
li{
padding: 5px 0;
}
.spanColor{
cursor: pointer;
}
}
</style>
<script>
// import treeMenus from './treeMenu2.vue'
export default {
name: 'treeMenus',
props: {
list: Array
},
data() {
return {
scopesDefault: [],
scopes: [],
tree: null,
}
},
methods: {
changeStatus(index,item) {//切换展开
this.$set(item,'expendclick',!item.expendclick)
if (this.scopesDefault[index] == true) {
this.$set(this.scopesDefault, index, false)
} else {
if(this.scopes[index]){
this.$set(this.scopesDefault, index, this.scopes[index])
}else{
if(this.scopes[index]===undefined){
this.$set(this.scopesDefault, index, true)
}else{
this.$set(this.scopesDefault, index, false)
}
}
}
},
scope() {//是否展开下一级
this.list.forEach((item, index) => {
this.scopesDefault[index] = false
if ('cList' in item) {
this.scopes[index] = true
} else {
this.scopes[index] = false
}
})
},
changValue(item){ //checkbox的选中与取消
// if(!item.checked){
this.$set(item,'indeterminate',item.checked) //切换indeterminate 状态,只负责样式控制
// }
console.log(item,'1111111111111111111111')
if(item.cList&&item.cList.length){
this.searchList(item.cList,item.checked)
}
this.tree.getResult(item.parentId)//在终极父组件中修改父级显示样式
},
searchList(arr,check){//对所有子集进行统一控制
arr.map(item=>{
this.$set(item,'checked',check)
this.$set(item,'indeterminate',check)
if(item.cList&&item.cList.length){
return this.searchList(item.cList,check)
}
})
}
},
created() {
let parent = this.$parent
while (parent && !parent.isTreeRoot) {
parent = parent.$parent
}
this.tree = parent //获取终极父组件
},
mounted(){
this.scope()
}
}
</script>
应用init.vue
</template>
<div class="eboss-col col-flex">
<label for="" class="form-label">业务区域<i>*</i>:</label>
<div class="form-control">
<div style="width: 100%">
<el-popover ref="business" placement="bottom-start" v-model="showSelect">
<div style="width: 300px; max-height: 200px; overflow-y: scroll">
<treeList :data="treeData" @check="getCheck" ref="trees" :props="{
label: 'areaName',
value:'id',
parentId:'parentId',
children: 'childList'
}" ></treeList>
</div>
</el-popover>
<div class="simulation-tags" @click.stop="showSelect = true">
<el-tag type="danger" size="small" closable
v-for="(item, index) in tags" @close="closeHandle(item)" :key="index"
>{{item.areaName}}</el-tag>
</div>
<div v-popover:business style="height:0"></div>
<!-- <el-popover ref="business" placement="bottom-start" v-model="showSelect">
<div style="width: 220px; max-height: 200px; overflow-y: scroll">
<el-tree ref="tree"
:data="treeData"
:props="{
label: 'areaName',
children: 'childList'
}"
node-key="originalId"
show-checkbox @check="checkTreeHandle"></el-tree>
</div>
</el-popover>
<div class="simulation-tags" @click.stop="showSelect = true">
<el-tag type="danger" size="small" closable
v-for="(item, index) in tags" @close="closeHandle(item)" :key="index"
>{{item.areaName}}</el-tag>
</div>
<div v-popover:business style="height:0"></div> -->
</div>
</div>
</div>
</template>
<script>
import treeList from 'module/newCkeckTree/treeList';
export default {
components:{
treeList,
},
data:{
},
methods:{
closeHandle (item) {
this.tags = this.tags.filter(tag => tag.id != item.id)
this.$refs.trees.setCheckedKeys(this.tags);
this.$set(this.query, 'businessAreaList', this.tags.map(item => item.id))
},
getCheck(item){
console.log(item,'huoqu')
this.tags=item
this.$set(this.query, 'businessAreaList', this.tags.map(item => item.id))
},
}
}
</script>
进行子集全选,父级默认选则
treeList.vue
<template>
<div>
<my-trees :list="list" @getResult="getResult" ref="treeMenu"></my-trees>
</div>
</template>
<script>
let vue=this;
import myTrees from './treeMenus'
export default {
components: {
myTrees
},
props:{
data: {//传入递归组件的原始数据
type: Array,
required: true
},
props:{//label,value,children,disabled,parentId(父子集关联数据)
type:Object
},
awlAll:{//如果传值为true,则子集全选,默认父级选择,如果不传值或者传值为false,子集全选,父级不选择
type:Boolean
}
},
data () {
return {
// list: [//实例
// {
// name: '一级',checked:false,expendclick:false,id:'1',parentId:'0',
// cList: [
// { name: '二级一',checked:false,expendclick:false,id:'21',parentId:'1' },
// {
// name: '二级二',checked:false,expendclick:false,id:'22',parentId:'1',
// cList: [
// { name: '三级',checked:false,expendclick:false,id:'31',parentId:'22', cList: [{ id:'41',parentId:'31',name: '四级' ,checked:false,expendclick:false,}] }
// ]
// }
// ]
// },]
list:[],
isTreeRoot:true,//验证真实根组件
checkList:[],//选中值
checkData:[],//返回选择值
}
},
mounted(){
},
watch:{
data(n,o){ // 监听收到转换前数据
// handler:(n,o) => {
if(n){
this.list=this.ruleList(JSON.parse(JSON.stringify(n)))
}
},
},
methods: {
async getResult(val){//接收子元素的,修改父元素
await this.searchList(this.list,val)
await this.getChecked()
},
async searchList(arr,val){
await arr.map(item=>{
if(item.id==val){//不管子元素如何变化,只要是点击子元素就要把父级元素checked改为false
if(this.awlAll){
let codes=item.cList.every(vall=>{
return vall.checked==true
})
if(codes){
this.$set(item,'checked',true)
if(item.parentId){//只要有父级元素就进行上级递归
this.searchList(this.list,item.parentId)
}
}else{
this.$set(item,'checked',false)
}
}else{
this.$set(item,'checked',false)
}
let code=item.cList.every(vall=>{
return vall.checked==false&&vall.indeterminate==false
})
if(!code){
this.$set(item,'indeterminate',true) //只要子级元素checked与indeterminate有true,则父级的indeterminate比为true
if(item.parentId){//只要有父级元素就进行上级递归
this.searchList(this.list,item.parentId)
}
}else{
this.$set(item,'indeterminate',false)//只要子级元素checked与indeterminate全部为false,则父级的indeterminate比为false
if(item.parentId){//只要有父级元素就进行上级递归
this.searchList(this.list,item.parentId)
}
}
// if(item.parentId&&item.parentId!=='0'){//没有父级时进行上级递归
// this.getResult(item.parentId)
// }
}else{
if(item.cList&&item.cList.length){
return this.searchList(item.cList,val) //下级递归
}
}
})
},
setCheckedKeys(arr){ //设置选中
let datas=JSON.parse(JSON.stringify(this.data))
this.list=this.ruleList(datas)
if(arr.length){
arr.map(item=>{
this.setcheckList(this.list,item[this.props.value])
})
}
},
setcheckList(arr,id){
arr.map(item=>{
if(item.id==id){
this.$set(item,'checked',true)
this.$refs.treeMenu.changValue(item)//将设置选中的值进行触发点击事件
}else{
if(item.cList&&item.cList.length){
this.setcheckList(item.cList,id)
}
}
})
},
async getChecked(){//获取选中元素并传递给父级组件
this.checkList=[]
this.checkData=[]
await this.searchCheck(this.list) // 获取转换后选中元素
this.checkList.map(item=>{
this.seaarchData(this.data,item.id) //获取转换前选中元素
})
this.$emit('check',this.checkData)//将转换前选中元素传递给父元素
},
searchCheck(arr){// 获取转换后选中元素
arr.map(item=>{
if(item.checked){
this.checkList.push(item)
}else{
if(item.cList&&item.cList.length){
return this.searchCheck(item.cList)
}
}
})
},
seaarchData(arr,id){//获取转换前选中元素
arr.map(item=>{
if(item[this.props.value]==id){
let ids=[]
if(this.checkData.length){
this.checkData.map(val=>{
return ids.push(val[this.props.value])
})
}
if(ids.indexOf(id)==-1){
this.checkData.push(item)
}
}else{
if(item[this.props.children]&&item[this.props.children].length){
return this.seaarchData(item[this.props.children],id)
}
}
})
},
ruleList(arr){//将接受到的值转换为需要样式
let arrs=arr.map(item=>{
// this.$set(item,"checked",false)
// this.$set(item,"expendclick",false)
item.checked=false
item.expendclick=false
item.indeterminate=false
if(this.props.label){//元素属性替换
let regExp = new RegExp(this.props.label, 'g');
item=JSON.parse(JSON.stringify(item).replace(regExp,"name"));
}
if(this.props.children){
let regExps = new RegExp(this.props.children, 'g');
item=JSON.parse(JSON.stringify(item).replace(regExps,"cList"));
}
if(this.props.value){
let regExpid = new RegExp(this.props.value, 'g');
item=JSON.parse(JSON.stringify(item).replace(regExpid,"id"));
}
if(this.props.parentId){
let regExpparentId=new RegExp(this.props.parentId, 'g');
item=JSON.parse(JSON.stringify(item).replace(regExpparentId,"parentId"));
}
if(this.props.disabled){
let regExpdisabled=new RegExp(this.props.disabled, 'g');
item=JSON.parse(JSON.stringify(item).replace(regExpdisabled,"disabled"));
}
if(item.cList&&item.cList.length){
item.cList=this.ruleList(item.cList)
}
return item
})
return arrs
}
}
}
</script>