如何在 Element UI 表单中使用自定义组件

语言: CN / TW / HK

theme: channing-cyan

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

在 Element UI 中使用表单相关组件,比如 <el-input><el-select>,可以通过在 <el-form><el-form-item> 中设置表单属性,实现子组件 sizedisabled 等属性设置,以及表单校验功能。

那么自定义的组件如何实现这些功能?

业务背景

最近产品给我提个一个需求,创建商品的时候,给商品增加标签,标签不仅需要名字,还需要颜色。于是我写了个组件。

▶ 点击查看代码 ```html ```

展示一下组件的使用效果。

tag1.gif

size 和 disabled 属性的透传

Vue 有个较少用到的功能,provide 和 inject

这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效。

不过注意其不能替代 vuex 使用,provide 和 inject 绑定并不是可响应的

在 ElForm 源码中可以看到其为子组件注入了 elForm 属性,传入了其本身。 js export default { // ... name: 'ElForm', // ... provide() { return { elForm: this }; }, }

在 ElFormItem 用同样的方式注入了 elFormItem 属性 js export default { // ... name: 'ElFormItem', // ... provide() { return { elFormItem: this }; }, }

于是在子组件可以获取这两个属性 js export default { // ... inject: { elForm: { default: '' }, elFormItem: { default: '' } }, }

然后在子组件中使用这些属性,把之前 sizedisabled 全部改为 tagInputSizetagInputDisabled 就可以在子组件中引用表单统一设置的属性。

其中 this.$ELEMENT 是引入 Element 时,传入的全局配置对象。

js export default { // ... computed: { _elFormItemSize() { return (this.elFormItem || {}).elFormItemSize; }, tagInputSize() { return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size; }, tagInputDisabled() { return this.disabled || (this.elForm || {}).disabled; } }, }

自定义组件的校验

在配置表单校验规则时,子组件触发指定事件(blurchange)时会触发表单项的校验。

阅读源码,发现 ElFromItem 监听了下面两个事件

js this.$on('el.form.blur', this.onFieldBlur); this.$on('el.form.change', this.onFieldChange);

onFieldBlur()onFieldChange() 中又会去执行校验逻辑。所以我们需要在子组件触发 el.form.blurel.form.change 事件。

我们引入 Element UI 中的 emitter,通过其定义的 dispatch函数触发事件。回到我们的组件,加入如下代码。

```js import emitter from 'element-ui/src/mixins/emitter';

export default { // ... mixins: [emitter], // ... methods: { // ... onChange() { // ... this.dispatch('ElFormItem', 'el.form.change', this.tagList); } } } ```

其中 dispatch(componentName, eventName, params) 会向上寻找组件名为 componentName 的组件,并触发其 eventName 事件。

除此之外,还需要加一些对应样式,在校验失败时,组件会有红色边框,我们把组件和其他组件的错误样式统一。

css .el-form-item.is-error .tag-input .tag-list { border-color: #F56C6C; } .el-form-item.is-error .tag-input .tag-list.disabled { border-color: #DCDFE6; }

完整代码

▶ 点击查看代码 ```html ```

测试效果

taginput.gif

Demo代码:

▶ 点击查看代码 ```html ```