el-cascader改装后的级联选择器,父关联子,子不关联父


<template>
	<div>
		<el-cascader filterable ref="myCascader" :options="options" v-model="vop" :show-all-levels="false" collapse-tags
			@change="handleChange" :props="{children: 'children',label: 'name', 
                    value:'pkOrg', multiple: true, checkStrictly: true,
                     emitPath: false, expandTrigger:'click' 
                }" clearable>el-cascader>
		
	div>
template>
<script>
	export default {
		props: {
			// 级联树数据定义
			options: {
				type: Array,
				required: true,
				default: true
			},
			// 级联选择器一开始绑定值,需回显
			updateValue: {
				type: Array,
				required: true,
				default: true
			},
			// firstOrgId:Object,
		},
		data() {
			return {
				// 选中的值
				vop: [],
				// 临时存放的当前选中值,用于后期的点击对比,获得当前节点值
				tmpVop: [],
				// 临时存放的值,用于递归函数给选中值
				tmp: '',
			}
		},
		created() {
			this.handleChange()
		},
		watch: {
			/** v-model绑定得值 */
			vop: {
				handler(n) {
					// 如果数据发生变化
					if (n) {
						this.$emit('childByValue', this.vop)
					}
				},
				deep: true,
				immediate: true
			},
			/**  如果一开始就给级联选择器赋值了 */
			updateValue: {
				handler(n) {
					if (n) {
						// 拿到父级节点的值,进行回显
						this.vop = this.updateValue
						this.tmpVop = this.vop
					}
				},
				deep: true,
				immediate: true
			}
		},

		methods: {
			// 选中或取消选中后的赋值
			checkArr(value, options, operation) {
				console.log(value, options, operation,'myCascader')
				options.map((x) => {
					if (value === x.pkOrg) {
						// 选中value项,并循环该节点下的其他所有子节点选中
						if (x.children) {
							this.checkArrNull(x.children, operation)
						}
					} else if (x.children) {
						this.checkArr(value, x.children, operation)
					}
				})
			},
			checkArrNull(options, operation) {
				console.log(options, operation,"myCascader")
				options.map((x) => {
					// 如果有子项,则递归,没有则选中
					// 选中当前节点2判断子节点,有则继续递归
					if (operation === 'add') {
						this.tmp = this.tmp + ',' + x.pkOrg
					} else if (operation === 'sub') {
						this.tmp = this.tmp.split(',')
						// shanchu zhi
						this.tmp = this.removeValue(x.pkOrg, this.tmp)
						this.tmp = this.tmp.join(',')
					}
					if (x.children) {
						this.checkArrNull(x.children, operation)
					}
				})
			},
			// 获得点击change事件时点击节点的值
			valueChange(tmp1, tmp2,action) {
				console.log(tmp1,tmp2,"myCascader")
				//新数组用来接收遍历的
				let newTem1 = [];
				//循环
				tmp1.forEach((item) => {
					newTem1.push(parseInt(item))
				})
				//筛选出不同的数字
				let difference = [];
				if(action === 'add'){
					// 选中
					difference = tmp2.filter(x => newTem1.indexOf(x) == -1);
				}else{
					// 取消选中
					difference = newTem1.filter(x => tmp2.indexOf(x) == -1)
				}
				console.log(difference,"myCascader")
				return difference[0];
			},
			// 删除数组指定的值的元素
			removeValue(v, arr) {
				v = v.toString();
				console.log(v,arr,"myCascader")
				let index = arr.indexOf(v)
				console.log(index,"myCascader")
				if (index !== -1) {
					arr.splice(index, 1)
				}
				return arr
			},
			// 数组去重
			unique(arr) {
				var arr2 = arr.sort()
				var res = [arr2[0]]
				for (var i = 1; i < arr2.length; i++) {
					if (arr2[i] !== res[res.length - 1]) {
						res.push(arr2[i])
					}
				}
				return res
			},
			// 将options的value值按照value生成一组数组
			optionsToarr(options) {
				this.tmp = ''
				options.map((x) => {
					this.tmp = this.tmp + x.pkOrg + ','
					if (x.children) {
						this.optionsToarrChild(x.children)
					}
				})
			},
			optionsToarrChild(options) {
				options.map((x) => {
					this.tmp = this.tmp + x.pkOrg + ','
					if (x.children) {
						this.optionsToarrChild(x.children)
					}
				})
			},
			// change事件
			handleChange(value) {
				
				// 获得点击变化时的值,然后判断是加值还是减值。根据值去递归
				let valueCh = ''
				// 操作是选中还是取消
				let action = ''
				// 对比获得是选中还是取消操作
				if ((this.vop).length > 0) {
					console.log(this.tmpVop,this.vop,"myCascader")
					if ((this.tmpVop).length > (this.vop).length) {
						valueCh = this.valueChange(this.tmpVop, this.vop,'sub')
						action = 'sub'
					} else {
						valueCh = this.valueChange(this.tmpVop, this.vop,'add')
						action = 'add'
					}
				}
				if (valueCh) {
					console.log(this.options,"myCascader")
					this.tmp = this.vop.join(',')
					this.checkArr(valueCh, this.options, action)
					// 去重
					this.vop = this.unique(this.tmp.split(','))
				}
				// 获得options的value值一维数组,用于排序对照
				this.optionsToarr(this.options)
				if (this.tmp.substring(this.tmp.length - 1) === ',') {
					this.tmp = this.tmp.substring(0, this.tmp.length - 1)
				}
				this.tmp = this.tmp.split(',')
				// 排序
				this.vop.sort((prev, next) => {
					return this.tmp.indexOf(prev) - this.tmp.indexOf(next)
				})
				this.tmpVop = this.vop
			}
		},
		created() {
			// 创建时默认给tmpVop赋值
			this.tmpVop = this.vop
		}
	}
script>

<style scoped="scoped" lang="scss">
	/deep/ .el-cascader .el-cascader__tags .el-cascader__search-input{
		display: none !important;
	}
	
style>


组件用法:

<-- updateValue : 当前选中的值    childByValue : 数据发生改变 子传父事件  options  组织树  -->
<myCascader v-model="updateVaule" :updateValue="updateVaule" class="sszz_cascader"
	v-on:childByValue="childByValue" :options="orgs">
myCascader>
`

你可能感兴趣的:(vue,前端,vue.js,javascript)