关于el-cascader再次加载时,懒加载不回显的问题
关于el-cascader再次加载时,懒加载不回显的问题

关于el-cascader再次加载时,懒加载不回显的问题

关于el-cascader再次加载时,懒加载不回显的问题

前情提要

在项目中使用form表单,提交地区code编码

该编码的节点使用el-cascader的懒加载,正常表单的回显完全没有问题

问题详情

第一次,加载 [‘3501′,’350101’] 会回显数据

第二次,加载 [‘3501′,’350101′,’35010102′,’3501010202’] 时,text不回显

即层数更多时不回显

代码如下,没有问题

<template>
<el-form-item label="地区" prop="dqs">
    <el-cascader
                 v-model="dqs"
                 :options="regions"
                 :props="{ checkStrictly: true, value: 'code', label: 'name', leaf: 'hasChildren', lazy: true, lazyLoad: lazyLoad }"
                 style="width: 447px"
                 @change="regionChange"
                 :disabled="IsSelfDisabled"
                 placeholder="地区"
                 clearable>
    </el-cascader>
    </el-form-item>
</template>
<script>
    export default {
        data() {
            return {
                regions: [{
                    value: 'code',
                    label: '',
                    children: [],
                },{xxx},{xxx}],
                dqs: ['3501','350101']
            }
        },
        methods: {
            lazyLoad(node, resolve) {
                if (node.value && node.value.length === 12) {
                    resolve()
                    return
                }
                setTimeout(() => {
                    POST({ code: node.value }).then(res => {
                        res.data.forEach(item => {
                            item.hasChildren = !item.hasChildren
                        })
                        resolve(res.data)
                    })
                }, 100)
            }
        }
</script>

解决过程

断点查看时发现,二次加载的时候,只回调了一次lazyLoad

明显不对,遂跟进js调用链

lazyLoad(cascader-panel)->lazyLoad(vue)->lazyLoad(cascader-panel)(resolve)

即没有重复调用lazyLoad的原因应该在cascader-panel的lazyLoad里

查看js代码,下断点

//node_modules/element-ui/lib/cascader-panel.js
lazyLoad: function lazyLoad(node, onFullfiled) {
    var _this5 = this;

    var config = this.config;

    if (!node) {
        node = node || { root: true, level: 0 };
        this.store = new src_store([], config);
        this.menus = [this.store.getNodes()];
    }
    node.loading = true;
    var resolve = function resolve(dataList) {
        var parent = node.root ? null : node;
        dataList && dataList.length && _this5.store.appendNodes(dataList, parent);
        node.loading = false;
        node.loaded = true;

        // dispose default value on lazy load mode
        if (Array.isArray(_this5.checkedValue)) {
            var nodeValue = _this5.checkedValue[_this5.loadCount++];
            var valueKey = _this5.config.value;
            var leafKey = _this5.config.leaf;

            if (Array.isArray(dataList) && dataList.filter(function (item) {
                return item[valueKey] === nodeValue;
            }).length > 0) {
                var checkedNode = _this5.store.getNodeByValue(nodeValue);

                if (!checkedNode.data[leafKey]) {
                    _this5.lazyLoad(checkedNode, function () {
                        _this5.handleExpand(checkedNode);
                    });
                }

                if (_this5.loadCount === _this5.checkedValue.length) {
                    //此处为 回显文本赋值 的函数
                    _this5.$parent.computePresentText();
                }
            }
        }

        onFullfiled && onFullfiled(dataList);
    };
    config.lazyLoad(node, resolve);
}

分别对20,25,38,45行断点,发现在二次调用时,25行的

ataList.filter(function (item) {
  return item[valueKey] === nodeValue;
}

返回了一个空数组 [] (即当前的节点数据中并不包含nodeValue的值)

导致二次调用并没有在28~39行内被断下,而直接返回,也不触发下一次懒加载

控制台输出发现

nodeValue = '3501010202'
item['code'] = '3501'

就很离谱,明明传的 checkedValue 是 ['3501','350101','35010102','3501010202']这么长的数据,他应该从第一个节点遍历的,为啥跑到了第四个

查看第21行的赋值语句发现 var nodeValue = _this5.checkedValue[_this5.loadCount++];

_this5.loadCount的值在20行的时候就已经是3了

而且这个值只在该函数调用,在data中初始化为0

这下就明白了,上一次使用 el-cascader 的数据没有被销毁,而是留到了这次渲染上了

解决方案

在新起的form 或 form提交后 销毁 el-cascader 即可

<template>
<el-form-item label="地区" prop="dqs">
    <el-cascader
                 v-if="dqs.length"   //添加此处,通过表单清空数据,根据v-if特性,来销毁el-cascader组建,达成重置loadCount的操作
                 v-model="dqs"
                 :options="regions"
                 :props="{ checkStrictly: true, value: 'code', label: 'name', leaf: 'hasChildren', lazy: true, lazyLoad: lazyLoad }"
                 style="width: 447px"
                 @change="regionChange"
                 :disabled="IsSelfDisabled"
                 placeholder="地区"
                 clearable>
    </el-cascader>
    </el-form-item>
</template>

总结

可以归咎为组件的数据回收问题,不过也惊醒我们一些懒加载的组件还是勤销毁比较重要