el-table通过这样封装可以实现校验-表格校验的原理_eltable封装原理

在这里我不太理解prop为什么要写成"'tableData.' + scope.$index + '.' + item.prop"这个样子就实现了校验的效果。后来在一次项目中偶然去查看了一下el-form的源码,才明白其中的道理;
在这里插入图片描述
首先我们看到el-form组件的文件路径是这样的,那么其实form-item是一个单独的组件,我们通过form -> form-item嵌套的时候,其实最后实现校验的过程是一个个去校验 form-item,form组件最终的校验:

// 最主要的核心功能
validate(callback){
  this.fields.forEach(field => {
  field.validate('', (message, field) => {
    if (message) {
      valid = false;
    }
    invalidFields = objectAssign({}, invalidFields, field);
    if (typeof callback === 'function' && ++count === this.fields.length) {
      callback(valid, invalidFields);
    }
  });
});
}

其中 this.fields就是el-form-item集合:

// el-form的created中
this.$on('el.form.addField', (field) => {
  if (field) {
    this.fields.push(field);
  }
});

// el-form-item的mounted中
this.dispatch('ElForm', 'el.form.addField', [this]);

// 内部自己使用 dispatch实现组件通讯

其中最主要的就是调用el-form-itemvalidate方法:

validate(trigger, callback = noop) {
        this.validateDisabled = false;
        const rules = this.getFilteredRule(trigger);
        if ((!rules || rules.length === 0) && this.required === undefined) {
          callback();
          return true;
        }

        this.validateState = 'validating';

        const descriptor = {};
        if (rules && rules.length > 0) {
          rules.forEach(rule => {
            delete rule.trigger;
          });
        }
        descriptor[this.prop] = rules;

        const validator = new AsyncValidator(descriptor);
        const model = {};

        model[this.prop] = this.fieldValue;

        validator.validate(model, { firstFields: true }, (errors, invalidFields) => {
          this.validateState = !errors ? 'success' : 'error';
          this.validateMessage = errors ? errors[0].message : '';

          callback(this.validateMessage, invalidFields);
          this.elForm && this.elForm.$emit('validate', this.prop, !errors, this.validateMessage || null);
        });
      }

其中主要的核心功能是单个的 rules(校验规则)model(数据)
rules的获取:

// 首先通过getFilteredRule方法过滤rules
getFilteredRule(trigger) {
  // 获取 rules
  const rules = this.getRules();
  return rules.filter(rule => {
    if (!rule.trigger || trigger === '') return true;
    if (Array.isArray(rule.trigger)) {
      return rule.trigger.indexOf(trigger) > -1;
    } else {
      return rule.trigger === trigger;
    }
  }).map(rule => objectAssign({}, rule));
},

// getFilteredRule最核心的方式就是getRules
getRules() {
  // 这个就是我们在 el-form中传递的rules
  let formRules = this.form.rules;
  // 这个就是我们自己在 el-form-item传递的rules
  const selfRules = this.rules;
  // 这里判断是不是必输的
  const requiredRule = this.required !== undefined ? { required: !!this.required } : [];
  // 这里通过formRules结合prop获取最新的prop(其实是一个对象,里面有key,value比较重要的值)
  const prop = getPropByPath(formRules, this.prop || '');
  formRules = formRules ? (prop.o[this.prop || ''] || prop.v) : [];
  // 最终将rules做一个整合
  return [].concat(selfRules || formRules || []).concat(requiredRule);
},

最终我们通过分析发现其实去匹配 el-form中整体的rules是通过getPropByPath这个方法的:

function getPropByPath(obj, path) {
  let tempObj = obj;
  path = path.replace(/\[(\w+)\]/g, '.$1');
  path = path.replace(/^\./, '');
  let keyArr = path.split('.');
  let i = 0;
  for (let len = keyArr.length; i < len - 1; ++i) {
    let key = keyArr[i];
    if (key in tempObj) {
      tempObj = tempObj[key];
    } else {
      throw new Error('please transfer a valid prop path to form item!');
    }
  }
  return {
    o: tempObj,
    k: keyArr[i],
    v: tempObj[keyArr[i]]
  };
}

path.split('.')这里会对prop进行切割,我们最终得到的值其实是这样的:
在这里插入图片描述
最终通过formRules = formRules ? (prop.o[this.prop || ''] || prop.v) : [];formRules这个值变成了undefined
再返回validate方法里面,看model,通过这里model[this.prop] = this.fieldValue,我们来看fieldValue

function getPropByPath(obj, path) {
  // 这里的值其实一个对象数组:


### 最后

如果你已经下定决心要转行做编程行业,在最开始的时候就要对自己的学习有一个基本的规划,还要对这个行业的技术需求有一个基本的了解。有一个已就业为目的的学习目标,然后为之努力,坚持到底。如果你有幸看到这篇文章,希望对你有所帮助,祝你转行成功。



![](https://img-blog.csdnimg.cn/img_convert/54a6b04f29167333b139d2753f60db9f.png)
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个基于 Element UI 的 el-table 中输入框校验的完整代码示例: ```html <template> <div> <el-table :data="tableData"> <el-table-column prop="name" label="姓名"></el-table-column> <el-table-column prop="age" label="年龄"> <template slot-scope="scope"> <el-form-item :prop="'age.' + scope.$index"> <el-input v-model="scope.row.age" @blur="validate(scope.$index)"></el-input> </el-form-item> </template> </el-table-column> </el-table> </div> </template> <script> export default { data() { return { tableData: [ { name: '张三', age: '' }, { name: '李四', age: '' }, { name: '王五', age: '' } ] } }, methods: { validate(index) { const age = this.tableData[index].age if (!age || isNaN(age)) { this.$refs.elForm.validateField(`age.${index}`, err => { if (err) { this.$refs.elTable.$el.querySelector(`.el-table__row:nth-of-type(${index + 1}) .el-input__inner`).style.border = '1px solid red' } else { this.$refs.elTable.$el.querySelector(`.el-table__row:nth-of-type(${index + 1}) .el-input__inner`).style.border = '' } }) } else { this.$refs.elTable.$el.querySelector(`.el-table__row:nth-of-type(${index + 1}) .el-input__inner`).style.border = '' } } } } </script> ``` 上述代码中,我们在 el-table-column 中使用了作用域插槽,通过 `scope.row.age` 和 `scope.$index` 分别绑定了表格数据中对应的 age 值和索引。 在输入框的 blur 事件中,我们调用了 `validate` 方法,该方法中通过 `this.$refs.elForm.validateField` 校验了当前输入框的值,并根据校验结果来改变输入框边框的颜色。 需要注意的是,在 `validateField` 校验方法的回调函数中,我们通过 `this.$refs.elTable.$el.querySelector` 获取了当前输入框所在行的 DOM 节点,并手动设置了其边框的样式。如果校验失败,我们将边框颜色设置为红色,否则清空样式即可。 希望这个示例对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值