属性透传与实传
实传:prop 指定传递的属性; 透传:未指定 prop 传递的属性传递给子组件嵌套组件
透传实现:
以 二次封装 ui 组件 场景为例
应用的 api: $attrs, $listeners, inheritAttrs, 渲染函数
// 父组件
<MyButton name="测试透传" type="error" :disabled="false" @click="clickBtn" />
// 子组件
const MyButton = {// 将未被 props 指定的属性 (不包含 style,class) 和不含 .native 修饰符的事件监听器绑定到子组件 Button 上
template: `<div class="box">
<Button v-bind:type="type" v-bind="$attrs" v-on="$listeners" />
</div>`,
components: {Button,},
inheritAttrs: false, // 禁止未被 props 指定的属性利用到组件根元素上
props: {
type: {
type: String,
default: 'primary',
},
},
created() {console.log(this.$attrs); // {name: '测试透传', disabled: false}
console.log(this.$listeners); // {click: f}
},
};
// ui 组件 Button, 间接应用如下
<Button type="primary" name="测试文本" icon="xxx" disabled @click="xxx" />
.native 绑定事件到子组件根元素
$listeners 可用于将事件监听器指向到具体的某个子元素,应用更灵便
将原生事件绑定到组件
引申应用:动静组件透传实现
在下面案例的根底上实现动静生成表单内容
// template
<div v-for="(config, index) in configArr" :key="config.type + index">
<!-- 动静组件,依据配置中的 Type 来决定渲染的是 Input 还是 Select -->
<component :is="config.type" :configProps="config.props"></component>
</div>
// configArr
[{
type: 'Input',
props: {
placeholder: '我是默认值',
clearable: true
}
}, {
type: 'Button',
props: {type: 'default'}
}]
// 注册新的组件, 应用渲染函数以代替动静组件
// 应用渲染函数解构 props,获取 attribute 绑定
const CompFormItem = {
components: {Input, Select},
name: 'FormItem',
props: {
config: {required: true}
},
render (h) {
// 第一个参数就是配置中的 type,也就是咱们的组件名称
return h(`${this.config.type}`, {
props: {...this.config.props || {}
},
attrs: {...this.config.props || {}
}
})
}
}
// 应用组件
<FormItem :config="config"></FormItem>
—– 对于 vue3.x 的变更 —–
- $listeners 被移除,事件监听器整合到 $attrs 中
- $attrs 蕴含 style、class 属性
- .native 修饰符移除,子组件未定义触发的事件,将被作为子组件的根元素的原生事件监听