VUE 组件二次封装v-bind 和v-on使用

本文介绍了Vue 2.4.0新增特性,即在子组件中如何利用v-bind='$attrs'和v-on='$listeners'进行属性和事件的二次封装。通过示例展示如何在子组件中传递父组件的所有属性和监听器,简化组件复用过程。

VUE 组件二次封装之v-bind=“$attrs” 和v-on="$listener"

vue 2.4.0 新增

//子组件
<template>
  <div>
    <el-button v-bind="$attrs">确定</el-button>
  <div>
</template>
 
// 父组件使用
<my-button type='primary' size='mini'/>

<think>我们正在二次封装一个a-input组件(假设是AntDesignVue的Input组件),需要透传所有属性、事件、插槽props。在Vue2中,我们可以使用以下方法:1.属性(Attributes)Props:使用`v-bind="$attrs"`可以传递非prop属性。注意,组件的props中已经声明的属性不会包含在`$attrs`中。2.事件(Events):使用`v-on="$listeners"`可以传递所有事件监听器。3.插槽(Slots):手动传递所有插槽,包括默认插槽具名插槽。但是,在封装时,我们通常需要处理以下几点:-使用`inheritAttrs:false`来防止属性自动添加到组件的根元素上(因为我们希望它们传递到内部的a-input上)。-对于props,如果我们在封装组件中声明了某个prop,那么它就不会在`$attrs`中,所以我们需要显式传递。但如果我们希望透传所有props,那么我们不应该在封装组件中声明它们(除了我们需要处理的个别prop)。然而,有时我们需要对某些prop进行特殊处理(如value),这时我们需要声明这些prop,并在内部组件上显式绑定。对于插槽,我们需要在封装组件中手动将每个插槽传递给内部组件。我们可以使用`$slots`对象来获取所有插槽,然后动态传递。另外,注意事件监听器已经通过`v-on="$listeners"`传递,所以不需要单独传递事件。下面是一个示例,展示如何封装a-input组件,透传所有属性、事件、插槽,并处理value的双向绑定(因为a-input通常使用v-model):</think>在 Vue2 中二次封装 `a-input` 组件并透传所有属性、props、事件插槽,可通过以下方案实现: ### 完整封装方案 ```html <template> <a-input v-bind="mergedAttrs" v-on="$listeners" :value="innerValue" @change="handleChange" > <!-- 透传所有插槽 --> <template v-for="(_, slotName) in $slots" #[slotName]="slotProps"> <slot :name="slotName" v-bind="slotProps" /> </template> </a-input> </template> <script> export default { name: 'WrappedAInput', inheritAttrs: false, // 阻止自动继承属性到根元素 props: { value: [String, Number], // 显式声明需要特殊处理的prop // 其他需要覆盖的prop可在此声明 }, data() { return { innerValue: this.value }; }, computed: { // 合并属性(排除已声明的props) mergedAttrs() { return { ...this.$attrs, // 未声明的属性 // 可在此添加覆盖属性 }; } }, watch: { value(newVal) { this.innerValue = newVal; } }, methods: { handleChange(e) { this.innerValue = e.target.value; this.$emit('input', this.innerValue); // 支持v-model this.$emit('change', e); // 透传原生事件 } } }; </script> ``` ### 关键实现说明: 1. **属性透传** - 使用 `v-bind="mergedAttrs"` 合并未声明的属性 - `inheritAttrs: false` 阻止属性绑定到根元素[^1] 2. **事件透传** - `v-on="$listeners"` 透传所有事件监听器[^2] - 显式处理 `input` 事件支持 `v-model` 3. **插槽透传** - 动态遍历 `$slots` 透传所有插槽(包括默认插槽具名插槽)[^3] ```html <template v-for="(_, slotName) in $slots" #[slotName]="slotProps"> <slot :name="slotName" v-bind="slotProps" /> </template> ``` 4. **Prop 处理** - 显式声明需要特殊处理的 `props`(如 `value`) - 未声明的 `props` 自动通过 `$attrs` 传递 5. **双向绑定** - 通过 `innerValue` 中转实现受控组件 - 在 `handleChange` 中同步触发 `input` `change` 事件 ### 使用示例 ```html <wrapped-a-input v-model="username" placeholder="透传属性示例" allow-clear @pressEnter="handleEnter" > <!-- 透传前置插槽 --> <template #prefix> <user-outlined /> </template> <!-- 透传后置插槽 --> <template #suffix> <tooltip title="额外信息"> <info-circle-outlined /> </tooltip> </template> </wrapped-a-input> ``` ### 注意事项 1. **特殊属性覆盖**:如需覆盖 `a-input` 的默认属性(如 `size`),在 `mergedAttrs` 计算属性中处理 2. **作用域插槽**:通过 `v-bind="slotProps"` 透传作用域插槽参数 3. **性能优化**:大量插槽时建议使用渲染函数优化
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值