昨天写了一个根据本公司业务去继承 elementUi 组件的类,今天就悲催的发现,继承适用性不大;
尤其是对于 el-select 之类的组件,有内部绑定时,绑定的是外部组件的属性,而不是绑定的 el-select 组件的属性,
但是,俺的组件不能去控制外部父组件的属性;
于是今天又改写成 wrap 了,简单来说,
就是类似于 EhayInput 这样的 组件里面会包裹一个 el-input , 于这样 <template><el-input......</template> 的模板语法
但是需要实现几个目标:
1. 组件需要能够自动把父组件传递的 prop 传递给里面的 el-input ;
就是 <EhayInput :max="10"></EhayInput> 这样写时, EhayInput 里面的 el-input 也应该自动绑定 max=10
2. 自动向上传递事件
也就是里面 el-input 的 focus 之类的事件应该会自动传递到 EhayInput , 类似于这样 <EhayInput @focus="focus"></EhayInput>
3. 自动绑定 slot,
也就是里面EhayInput 的 slot 之类的定义应该会自动传递到里面的 el-input , 类似于这样
<EhayExample ref="wrap"><template slot="prepend">Http://</template></EhayExample> 这个 http:// 应该传递到 里面的 el-input 组件里面。。。
简单来说,就是尽量让组件用起来不变 或者 更加方便;
先来看看第一个目标,
1. 组件需要能够自动把父组件传递的 prop 传递给里面的 el-input ;
就是 <EhayInput :max="10"></EhayInput> 这样写时, EhayInput 里面的 el-input 也应该自动绑定 max=10
这个貌似不难,有2个基本方法,
a. 老老实实的写 模板定义, 把被包裹的所有 prop 重新绑定到自己组件的 prop 上, 反正自己组件也是 mixins 了 ElInput 组件,所以自己的组件也肯定包含 ElInput 组件 所有的 prop 属性,直接绑定毫无问题;
<template>
<ElInput ref='innerOriginal' :value='value' :size='size' :resize='resize' :form='form' :disabled='disabled' :readonly='readonly' :type='type' :autosize='autosize' :autocomplete='autocomplete' :autoComplete='autoComplete' :validateEvent='validateEvent' :suffixIcon='suffixIcon' :prefixIcon='prefixIcon' :label='label' :clearable='clearable' :tabindex='tabindex' ></ElInput>
</template>
b. 自动产生上面的模板字符串,并编译成为相应的 render 函数,
简单来说,就是把上面这个模板字符串自己拼凑出来,并编译成 render 函数
(如果你定义了 template, 这一步VUE会自动完成)
这个也很简单。。。。加一个 ref 是为了在自己的组件中能够引用里面这个 el-input 组件
class Compile {
/**
* 根据组件定义产生 组件的定义 template 字符串,并通过 Vue编译后,产生 render 函数;
* @param c ElementUI 组件的实例,好稀奇, 传入 elementUI.Input 应该是一个 class 定义,
* 但是却传入了 类实例;
*/
static compile(c: any): (createElement: any) => VNode {
let result: string = '';
result = "<" + c.name + " ref='innerOriginal' ";
for (let prop in c.props) { // 绑定组件中的属性
result = result + ' :' + prop + "='" + prop + "' ";
}
result += ">";
result += "</" + c.name + ">";
console.log(result);
return Vue.compile(result).render;
}
}
然后我们再用 昨天提到的 方法继承一个 el-input 组件
/**
* 自动完成组件
* 使用方法,继承自 elementUI.Input, 和 elementUI.Input 一样使用即可;
* <EhayInput entityTypeName='EH_Client' v-model='client'></EhayInput>
* 但是有个问题,因为是远程查询,所以绑定时可能会
*/
@Component({
template: `<div>abc</div>`,
render: Compile.compile(elementUI.Input),
})
export default class EhayInput extends Mixins(elementUI.Input) {
.....
如果,你不理解 @Component, 请查看
https://github.com/kaorun343/vue-property-decorator, 或者 https://github.com/vuejs/vue-class-component , 不过,
貌似不太可能,使用 vue + typescript , 很难不使用这2者之一。。。
以上2个项目代码质量极高,且文档非常优秀,上千个 Star 只有不到10个 Issues.
今天先到这儿。。