如何在 Element UI 表单中使用自定义组件
theme: channing-cyan
小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
在 Element UI 中使用表单相关组件,比如 <el-input>
、<el-select>
,可以通过在 <el-form>
和 <el-form-item>
中设置表单属性,实现子组件 size
,disabled
等属性设置,以及表单校验功能。
那么自定义的组件如何实现这些功能?
业务背景
最近产品给我提个一个需求,创建商品的时候,给商品增加标签,标签不仅需要名字,还需要颜色。于是我写了个组件。
▶ 点击查看代码
```html ```展示一下组件的使用效果。
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: ''
}
},
}
然后在子组件中使用这些属性,把之前 size
和 disabled
全部改为 tagInputSize
和 tagInputDisabled
就可以在子组件中引用表单统一设置的属性。
其中 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;
}
},
}
自定义组件的校验
在配置表单校验规则时,子组件触发指定事件(blur
或 change
)时会触发表单项的校验。
阅读源码,发现 ElFromItem
监听了下面两个事件
js
this.$on('el.form.blur', this.onFieldBlur);
this.$on('el.form.change', this.onFieldChange);
在 onFieldBlur()
和 onFieldChange()
中又会去执行校验逻辑。所以我们需要在子组件触发 el.form.blur
或 el.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 ```测试效果
Demo代码: