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);
          });
        }
      }
    }, 

  

posted @ 2022-05-12 22:33  秦皇汉武  阅读(5026)  评论(0编辑  收藏  举报