关于扩展Element组件库的一些思考
2020-03-26 本文已影响0人
为了鱼丸
ElementUI是所有Vue组件库中比较优秀的一个,至今已经在github收获了44.3k个star,公司几乎所有的Vue项目都是使用ElementUI作为基础组件库,其丰富的组件足以应付大部分交互场景,但是碰到特殊的需求组件库内的组件没法满足应用场景我们该怎么办呢?这个时候就需要我们动手扩展当前的组件库来满足我们的应用场景。
扩展组件库可能遇到的问题
试想这样一个场景,现在项目中要用到日期范围组件,要求开始日期和结束日期可以分别选择,并且能够对某些日期进行禁用,组件库里面并没有这样的组件,你会怎样实现这样的需求?
- 实现这样一个表单控件,如何进行表单的验证?
你需要从element-ui/src/mixins/emitter
引入Emitter这个事件分发的mixin,当值变化的时候调用this.dispatch("ElFormItem", "el.form.change", value)
来触发表单的校验 - 组件原有的属性我该如何在新的组件上继承使用?
这个涉及到组件的属性值穿透问题,Vue给我们提供了$attrs,在实际使用过程中,有些属性我们并不想从父级作用域传递下来,这时候你可以声明一个计算属性,对$attrs进行处理,删除或者增加你想要的属性 - 组件原有的事件侦听器我该如何在新的组件上继承使用?
Vue给我们提供了$listeners,在用法上和属性基本一致 - 想让我们封装的组件支持v-model命令该怎么做呢?
可以设置model: { prop: 'value', event: 'change' },
当你调用this.$emit('change',value)
的时候,value的值就会被改变,你可以watch这个value属性,当值发生变化的时候,对当前组件的data进行一些操作来满足一些需求 - 开发过程中需要表单组件的一些属性该怎么办?
如果你看过Form组件的源码,你会发现它使用了Vue的provide
,inject
属性,对于多层级嵌套的组件,这两个属性是很有用的,可以完成跨多层级的值传递,在我们自己的组件上,下面这段代码展示了inject有哪些用处 - 有些时候我们开发的组件有层级关系,跨组件通信怎么搞定?
如果我们自定义的组件相互之间有层级嵌套关系,可能以slot的形式嵌套,那么除了给组件设置name属性之外,还需要设置componentName,这个属性是为了使用broadcast 和 dispatch
方法来通信用的
export default {
inject: {
elForm: {
default: ''
},
elFormItem: {
default: ''
}
},
computed: {
_elFormItemSize() {
return (this.elFormItem || {}).elFormItemSize;
},
validateState() {
return this.elFormItem ? this.elFormItem.validateState : '';
},
needStatusIcon() {
return this.elForm ? this.elForm.statusIcon : false;
},
inputSize() {
return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
},
inputDisabled() {
return this.disabled || (this.elForm || {}).disabled;
},
},
我们可以从父级组件拿到表单的状态,比如大小,是否禁用
- 如何暴露我们的组件以Vue.use的形式来使用
MyComponent.install = function(Vue,options){
Vue.component(MyComponent,MyComponent.name)
}
export default MyComponent
我们可以这样使用
Vue.use(MyComponent,options)
结语
扩展组件开发,需要特别熟悉组件的用法,有些需要深入源码了解原理,根据原理制定开发方案,在探索的过程中,我们会遇到很多问题,这时可以去好好看看源码,或者去github issue列表寻找答案