自定义组件触发饿了么表单校验

饿了么的表单控件,如果存在自定义组件更改了值,例如在el-from中存在原生input组件很有可能没法触发表单校验,下拉框或者弹框组件仍然是报红边框。

这是因为饿了么的输入框或者下拉框更改值的时候会自动触发表单校验,但是封装过后的组件无法触发校验表单校验。那么此时可以手动触发饿了么的表单校验。

源码分析

在packages/form/src/form-item.vue中,可以找到addValidateEvents方法,该方法是用来给el-form-item的子组件绑定校验事件的,如下:

javascript 复制代码
addValidateEvents() {
  const rules = this.getRules();
  if (rules.length || this.required !== undefined) {
    this.$on('el.form.blur', this.onFieldBlur);
    this.$on('el.form.change', this.onFieldChange);
  }
}

在packages/input/src/input.vue中,可以找到el-input发送el.form.blur和el.form.change事件的代码,这里只贴出el.form.change的代码:

javascript 复制代码
watch: {
  value(val) {
    this.$nextTick(this.resizeTextarea);
    if (this.validateEvent) {
      this.dispatch('ElFormItem', 'el.form.change', [val]);
    }
  }
}

这里用了dispatch方法,该方法的代码在src/mixins/emitter.js中:

javascript 复制代码
dispatch(componentName, eventName, params) {
  var parent = this.$parent || this.$root;
  var name = parent.$options.componentName;
  while (parent && (!name || name !== componentName)) {
    parent = parent.$parent;
    if (parent) {
      name = parent.$options.componentName;
    }
  }
  if (parent) {
    parent.$emit.apply(parent, [eventName].concat(params));
  }
}

由此可以看出,要触发el-form的校验,需要el-form-item中的子组件去发布el.form.change或el.form.blur等事件,由el-form-item监听该事件,触发表单校验。

解决方案

方法一:在父页面中直接调用表单的校验方法validateField:

javascript 复制代码
watch: {
  'passwordForm.newPassword': function() {
    this.$refs.passwordForm.validateField('newPassword')
  }
}

方法二:在父页面中发布组件的el.form.change等事件:

javascript 复制代码
<input ref="input" @blur="handleBlur">
<script>
export default {
  methods: {
    handleBlur (val) {
      this.$refs.input.$emit('el.form.blur', val)
    }
  }
}
</script>

方法三:在子组件中发布el.form.change等事件,此时无需在父页面中做任何处理,其中dispatch方法直接将上面所说的emitter.js中的代码拷贝过来即可:

javascript 复制代码
export default {
  methods: {
    dispatch(componentName, eventName, params) {
      // ... 从emitter.js中拷贝过来的代码
    },
    handleInput (e) {
      this.$emit('input', e.target.value)
      this.dispatch('ElFormItem', 'el.form.change', [e.target.value])
    }
  }
}

以下是我某项目的解决方法,使用的方法2,即找到el-form-item然后触发el.form.change事件。

javascript 复制代码
 methods: {
	confirm() {
	      this.$emit("confirm", result);
	      this.$nextTick(() => {
	        parent && parent.$emit("el.form.blur", result); // 重点!触发表单校验 el.form.change, el.form.blur
       		parent && parent.$emit("el.form.change", result); // 重点!触发表单校验
      });
    },
   },
 // 找到el-form-item元素的代码
 mounted() {
   let parent = this.$parent;
   while (parent) { 
	   if (parent.$options.name === "ElFormItem") {
	     this.parent = parent;
	     break;
	   }
	   parent = parent.$parent;
   }
},
    

原文博客:非el组件/自定义组件触发el-form的校验

个人博客: 自定义组件触发饿了么表单校验

相关推荐
breeze jiang19 分钟前
React + WebGPU 在浏览器运行 DeepSeek:从 Worker 通信到流式生成
前端·javascript·react.js
sunly_37 分钟前
React 三个重要概念:Ref、Props、State 详解
前端·javascript·react.js
Mh44 分钟前
如何使用GSAP实现一个 `pinned` 滚动楼层叙事?
前端·javascript·css
Larcher7 小时前
React Router 不只是页面跳转:从 SPA 路由到权限守卫的完整实践
javascript·后端
Larcher7 小时前
大模型为什么每次回答都不一样?一文搞懂 Temperature、Top K 与 Top P
javascript·后端
eric-sjq10 小时前
10 分钟实战:用 0.6B 本地模型生成中文网页(WanlyFrontend + 编译器全流程)
javascript·机器学习·自然语言处理·html
To_OC11 小时前
LC 438 找到所有字母异位词:暴力超时后,我靠滑动窗口一招搞定
javascript·算法·leetcode
90后的晨仔11 小时前
Mac 开发 uni-app 终极方案:让安卓模拟器彻底脱离 Android Studio 独立运行
前端·vue.js
kyriewen12 小时前
面试官问"这段逻辑为什么这样写"——我才发现,这半年我写的代码,我自己都解释不了
前端·javascript·面试
一壶浊酒..12 小时前
Scrape Webpack练习
开发语言·javascript·webpack