1. el-cascader(包括avue.js)的编辑回显问题(针对lazyload懒加载)
问题(耗时我一天多):
编辑时回显数据。
两种情况:emitPath分别为false和True。
同时,checkStrictly始终为true(即允许选中的是中间层节点)。
一个是省市数据:
省市数据采取emitPath为True。
一个是部门数据:
部门数据采取emitPath为False。
后端处理:
针对省市数据,后端返回省市列表。形如["北京市","东城区"]。注意,是列表
针对部门数据,后端只返回一个部门的id值,并且非列表。
编辑回显规则(尽量不要设leaf,没必要。注意是label,value和children):
懒加载的编辑回显,我通过一天反复实验,总结出三条规则:
规则1.第一:lazyload中resolve的那个数据,其层次,必须能够与要显示的编辑回显值对应(能利用resolve的数据字典,搜索出要显示的回显值列表),并且层次大于回显值层次。比如,resolve的是省市区,那么回显值可以是只到省,也可以是省市,也可以是省市区。
即回显值的列表长度必须小于等于resolve数据的层次数
规则2.第二:当修改后端返回的部门数据的id值时,即令this.form.dept_id,改为列表时,组件会默认执行点击过程(即,可以利用alert输出一个node.level值。),这个默认的点击过程,至少执行一次。
比如,你传回的部门id是6,你为了能够满足前述规则1,通过搜索列表,将回显值改为列表["12","6"]。那么当改完以后,组件会默认执行点击过程(非node.level===0对应的lazyload加载过程),比如node.level==1。
规则3.当涉及后端数据返回时,由于执行的是Promise过程,在then中获取返回数据,需要写上await和async,避免出现数据未resolve,而组件已经加载完毕的情形(具体可以自行测试。不一定需要await和async。)
针对不修改回显值情形的籍贯数据(一次加载34省份数据,太大,需要懒加载)
以avue.js的option为例,下面是一个完整的option某个列籍贯的定义。
--》注解:
1.首先是加载el-cascader组件时,会在lazyload中执行node.level==0对应的加载过程,这个时候,我们需要利用safe.form.domicile(safe是this)方法来判定当前是编辑还是新增。
判断方法为:
if (!(safe.form.domicile === null || safe.form.domicile === undefined)) {
即有无值传入。
当无回显值列表传入的时候,我们在node.level==0中只加载最高一级的省数据。当有回显值传入时,为了回显,我们将该省的所有市数据全部resolve,保证resolve的数据层次大于回显值列表的宽度,保证回显。
2.其次,对于所有非node.level=0的情形,先判定当前node.data.childen有无数据(编辑回显时,resolve的数据已经有了。此时resolve([]),避免点击北京后,重复出现多个类似东城区的数据子列表。),如果没有,再获取value,利用getcity方法获取子数据即可。
《-- 注解。
{ filters: true, sortable: "custom", label: "籍贯", cell: true, prop: "domicile", xiaojieimport: true, type: "cascader", checkStrictly: true, lazy: true, formatter: (val, value, label) => { var sssss = ""; // alert(JSON.stringify(value)); // alert(value[0] + value[1]); if (value == null) { return ""; } else { if (value instanceof Array) { value.forEach((item) => { sssss += item; }); } } return sssss; }, lazyLoad: (node, resolve) => { // 这里要注意编辑回显 var result = []; if (node.level === 0) { // alert("0"); result = getProvince(); // alert(JSON.stringify(safe.form.domicile)); // alert(JSON.stringify(result)); // alert(safe.form.domicile); if (!(safe.form.domicile === null || safe.form.domicile === undefined)) { if (safe.form.domicile.length > 0) { // 编辑回显 // alert("编辑回显"); // 事实证明,只要result中的比传入的多即可。 // alert(safe.form.domicile[1]); var childrenList = getCity(safe.form.domicile[0]); // alert(JSON.stringify(childrenList)); var new_result = []; result.forEach((item) => { if (item["value"] === safe.form.domicile[0]) { item["children"] = childrenList; } new_result.push(item); // alert(JSON.stringify(new_result)); }); result = new_result; } } // alert(JSON.stringify(result)); resolve(result); } else { alert("回显会自动执行"); // 为了避免编辑回显时,已经加载了许多result,我们需要避免重复加载children if (!("children" in node.data && node.data["children"] !== [])) { node.data["children"] = []; result = getCity(node.data.value); // 该函数可以继续获取子city resolve(result); } else { resolve([]); } } }, search: true },
针对需要修改回显值情形的部门数据(从后端返回数据,位于then中执行回显)
我们存储的部门数据只是一个子部门的id(可以为中间部门。)比如,中央部、宣传办。可以是中央部的id,也可以是宣传部子部门的id。
虽然利用emitPath为false,将el-cascader的数据,只传一个值到后端。后端返回一个数。
但是,如果想顺利回显出“中央部/宣传部”的形式,必须转为列表。见前述回显规则1。
具体代码如下:
--》注解:
1.首先是加载el-cascader组件时,会在lazyload中执行node.level==0对应的加载过程,这个时候,我们需要利用safe.form.dept_id(safe是this)方法来判定当前是编辑还是新增。
判断方法同前。即有无值传入。
当无回显值列表传入的时候,我们只加载第一层部门数据。当有回显值传入时,我们利用递归方法,在字典数据中寻找该id,记录path,从而将一个部门id,变为能够加载回显的部门列表数据。具体见规则1。
然后,再一次执行获取全部部门数据的result,并且只resolve最高一层。(注意,这个能同于前述籍贯数据。因为籍贯数据中,不涉及修改回显值,所以,不存在默认点击的情形。而这里如果resolve全部数据,会造成只有顶层部门的回显值,无法成功回显。具体原因不明。可自行测试。)。
2.其次,对于所有非node.level=0的情形,这里不判定有无子数据,而是要直接搜寻所有子数据,并resolve。(具体原因不明,可自行测试)
3.针对需要修改回显值的情形,为什么用上述两个步骤使用,具体原因不明,但是绝对不同于前述籍贯数据(emitPath=true)。可能是vue.js中的一个bug。大家将就使用。
欢迎高手指导。
《-- 注解。
{ filters: true, sortable: "custom", label: "办公室", type: "cascader", cell: true, prop: "dept_id", search: true, ref: "office", checkStrictly: true, emitPath: false, xiaojieimport: true, lazy: true, formatter: (val, value, label) => { if ("dept_name" in val) { return val["dept_name"]; } else { return ""; } }, lazyLoad: async(node, resolve) => { var result = []; if (node.level === 0) { // alert("node level 0"); if (!(safe.form.dept_id === null || safe.form.dept_id === undefined)) { // 当等于1的时候 这个取值的过程不要放到 var l = []; l.push(safe.form.dept_id); safe.form.dept_id = l; // alert("Yyyy"); await getTreeselect_zhidingbumen().then(function(res) { // alert(JSON.stringify(res)); result = res; var objj = { flag: true, path: [], result: [], once: false, children: [] }; var path = []; findItem(result, safe.form.dept_id, objj, path); if (objj.path.length != 1) { // alert("Xxxx"); safe.form.dept_id = objj.path; //将部门数据变为部门列表数据 } }); await getTreeselect_zhidingbumen().then(function(res) { // alert(JSON.stringify(res)); result = res; for (var index in result) { if ("children" in result[index]) { delete result[index]["children"]; } result[index]["children"] = []; } resolve(result); }); } else { // 非编辑回显时,只加载第一层数据 getTreeselect_zhidingbumen().then(function(res) { // alert(JSON.stringify(res)); result = res; for (var index in result) { if ("children" in result[index]) { delete result[index]["children"]; } result[index]["children"] = []; } resolve(result); }); } } else { // 当执行完一次修改值的时候。 alert("回显"); alert(node.level); alert(JSON.stringify(node.data)); var pickValue = node.data.value; alert(pickValue); getTreeselect_zhidingbumen().then(function(res) { var objj = { flag: true, path: [], result: [], once: false, children: [] }; var path = []; // 当找到以后,返回该点击数据的children值。 findItem(res, pickValue, objj, path); // alert(JSON.stringify(objj.children)); if ("children" in objj) { objj.children.forEach((item) => { if ("children" in item) { delete item["children"]; } }); } // alert(JSON.stringify(objj.children)); resolve(objj.children); }); } } },