问题描述:
el-cascader组件在多选、懒加载模式下回写不成功
原因分析:
el-cascader组件下拉框选项未加载出来导致的value无法回写。(经试验发现,el-cascader组件单选模式下,只要将value数据结构转成组件接收的结构即可回写成功,懒加载的回调函数会自动触发执行。但是多选模式下,即使将value数据结构转成和组件接收的二维数组结构一样,也无法自动触发懒加载回调将下拉框选项加载出来。)
解决方案:
一般懒加载的级联只需要在props属性中定义lazyLoad函数加载动态数据,但是多选的成功回写还需要在组件中定义options属性并进行递归赋值!很重要!!!如果你也是级联多选懒加载模式下回写不成功一定试试这个方法!
下面贴代码说明options属性如何赋值。
代码:
1. 模板代码片
<el-cascader
ref="cascader"
v-model="form.dict"
v-loading="loading"
:props="props"
:options="cascaderOptions"
@change="handleChange"
/>
属性说明:
v-model:选中项绑定值
props:配置选项
options:可选项数据源
@change:当选中节点变化时触发
2. props配置代码片
props: {
value: 'code',
label: 'name',
checkStrictly: true, // 父子节点不关联
multiple: true, // 多选
lazy: true, // 懒加载
lazyLoad: async(node, resolve) => {
return this.getDict(node, resolve)
}
}
3. 获取数据接口代码片
async getDict(node, resolve) {
const {level, children} = node
let params = { dmId: this.currentId }
if (level > 0) {
params = {
dmId: this.currentId ,
parentCode: node.data.code
}
}
const { code, data } = await getDictList(params)
if (code !== '200') return this.$message.warning(data.error)
if (children && children.length) return resolve([]) // 解决重复数据问题
resolve(data, resolve)
},
以上代码可以实现新增级联数据成功,但是编辑这条数据的时候,是无法回写展示的,所以在编辑数据时,需要递归调用数据接口获取级联下拉框选项。
4. options赋值代码片
watch: {
editRow: {
async handler(val) {
this.currentId = val.id
this.form = {
...this.$options.data().form,
...val
}
this.$nextTick(() => {
this.initOptions() // 初始化级联下拉选,实现回写
})
}
}
},
// 初始化option
async initOptions() {
this.loading= true
this.cascaderOptions = []
const params = { dmId: this.currentId }
const { code, data } = await getDictList(params)
if (code !== '200') return this.$message.warning(data.error)
if (data.length) this.cascaderOptions = await this.loadOptions(data || [])
this.loading= false
},
// 递归加载子项目
async loadOptions(dict) {
const array = []
for (let i = 0; i < dict.length; i++) {
const params = {
dmId: this.currentId,
parentCode: dict[i].code
}
const { code, data } = await getDictList(params)
if (code !== '200') return this.$message.warning(data.error)
dict[i].children = await this.loadOptions(data)
array.push(dict[i])
}
return array
},
注意点及总结:
1. 递归加载options数据时,编辑数据成功回写,但是再次点击父节点,会手动触发回调请求数据接口,导致下级出现重复数据。
在懒加载回调函数中,加入这句 if (children && children.length) return resolve([]) 即可解决出现重复数据的问题。
2. 级联的lazyLoad函数触发的时机是该级联输入框渲染到页面时,因此,如果级联输入框是通过其他组件联动展示的,可以通过将其options置空来触发lazyLoad函数执行。
changeType(val) {
this.currentId = val
this.cascaderOptions = [] // 置空触发lazyLoad函数
},
3. 由于产品要求该级联选择可以任意选择某个节点,所以我将checkStrictly属性设置成父子节点不关联,这样父节点和子节点都是可以被勾选的。但是产品又要求勾选子节点时,就不要对应的父节点了,所以还需要写一个过滤父节点数据的算法,详情可以参考我的下一篇文章: el-cascader多选过滤掉已选节点的父节点.。
结果展示:
写在最后: 使用options属性虽然解决了多选、懒加载模式下级联下拉框的回写问题,但是初始化递归赋值的操作会造成多次接口请求,会导致级联框渲染初始值的时候很慢,尤其是节点多的情况下。目前我是递归请求上级返回结果的所有子节点,可以优化成递归请求选中节点的数据。如果有更好的方法欢迎分享。