前言
在我们的日常开发中经常会二次封装一些已有的组件,但是如果一个个的透传属性、事件、插槽等给已有组件的话那就太麻烦了,其实vue提供了属性、事件监听、插槽等批量透传的能力。
一、vue组件能力的透传
其实这种批量透传组件能力的属性和extend很像,都能够实现组件的”继承“。ps:后面可以单独再出一章讲解下extend的应用哈~
vue中批量透传属性可以使用v-bind:$attrs
,批量透传事件监听可以使用v-on:$listeners
,批量透传插槽可以遍历$slots
和$scopeSlots
,我们可以打印一下组件实例看看具体内容的。
当然如果某些能力不想透传的话,我们可以过滤掉$attrs
、$listeners
、$slots
和$scopeSlots
等的一些内容。
二、二次封装el-autocomplete组件
话不多说,直接上代码(以el-autocomplete为例)
子组件
<el-autocomplete
v-model="tempValue"
v-bind="$attrs"
v-on="$listeners"
>
<template v-for="(index, name) in $slots" :slot="name">
<slot v-if="!ignore_slot.includes(name)" :name="name"></slot>
</template>
<template v-for="(index, name) in $scopedSlots" v-slot:[name]="data">
<slot :name="name" v-bind="data"></slot>
</template>
</el-autocomplete>
<div class="append">
<slot name="append"></slot>
</div>
export default {
props: {
value: {
type: null
}
},
data() {
return {
ignore_slot: ['prepend', 'append'],
}
},
computed: {
tempValue: {
get() {
return this.value
},
set(v) {
this.$emit('input', v)
}
}
}
}
父组件
<inherit-autocomplete
ref="autocomplete"
class="inherit-input2"
v-model="value2"
size="small"
placeholder="我透传部分插槽"
:fetch-suggestions="querySearch"
@focus="focus"
@blur="blur"
>
<template slot="prefix">
<div class="fix">前面</div>
</template>
<template slot="suffix">
<i class="el-icon-edit fix"></i>
</template>
<template slot="prepend">
<div>无效的插槽</div>
</template>
<template slot="append">
<div>我是重新定义的插槽</div>
</template>
<template slot-scope="{ item }">
<div class="name">{{ item.value }}</div>
<span class="addr">{{ item.address }}</span>
</template>
</inherit-autocomplete>
<div>{{eventText}}</div>
export default {
components: {
InheritAutocomplete
},
data() {
return {
value1: '我是新组件',
value2: '',
restaurants: [
{ "value": "三全鲜食(北新泾店)", "address": "长宁区新渔路144号" },
{ "value": "Hot honey 首尔炸鸡(仙霞路)", "address": "上海市长宁区淞虹路661号" },
],
eventText: ''
}
},
methods: {
querySearch(queryString, cb) {
const results = queryString ? this.restaurants.filter(this.createFilter(queryString)) : this.restaurants;
// 调用 callback 返回建议列表的数据
cb(results);
},
createFilter(queryString) {
return (restaurant) => {
return (restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0);
};
},
focus() {
this.eventText='触发了聚焦事件'
},
blur() {
this.eventText='触发了失焦事件'
}
}
}
上面例子我们用了之前说的实现v-model的方法。在slot插槽的透传中,我们将append这个原有的具名插槽过滤了,并重新自定义了这个插槽,例子中使用了默认的作用域插槽用来格式化输入建议模板的内容,blur和focus的失焦和聚焦事件。
效果
三、总结
以上我们就实现二次封装组件能力的透传,不用自己把所有的属性、插槽、事件监听等额外都写一遍了。 可以参考github链接:github.com/qiangguangl…
下期预告: 了解到组件的功能透传之后,我们可以封装el-table组件了,不用一直写el-table-column了(频繁的写实在是太烦了。。。)