Vue3中ElementPlus组件二次封装,实现原组件属性、插槽、事件监听、方法的透传

本文以el-input组件为例,其它组件类似用法。
请添加图片描述

一、解决数据绑定问题

封装组件的第一步,要解决的就是数据绑定的问题,由于prop数据流是单向传递的,数据只能从父流向子,子想改父只能通过提交emit事件通知父修改。
父:

import { ref } from 'vue'
import CInput from '@/components/CInput/index.vue'

const name = ref<string>('')
<c-input v-model:value="name"/>

子组件:

import { ref, computed } from 'vue';
const props = withDefaults(defineProps<{
    value: string;
}>(), {
    value: ''
})
const inputValue = computed({
    get: () => props.value,
    set: (value: string) => emit('update:value', value)
})
<el-input
   v-model="inputValue" 
></el-input>

以上即可实现父子之前数据的双向传递。
但在Vue3.4+版本中,新增了defineModel() ,这个宏可以用来声明一个双向绑定 prop,通过父组件的 v-model 来使用:const model = defineModel()。同样实现了父子组件数据的双向绑定。感兴趣的同学可以看下官网解释,其有更多用法。

二、属性、事件监听

在vue3版本中,“透传 attribute”指的是传递给一个组件,却没有被该组件声明为 props 或 emits 的 attribute 或者 v-on 事件监听器。
例如el-input组件上有许多属性,clearable、show-word-limit、show-password、@input、@focus等等,这些肯定不需要通过props传递给子组件,那就是通过$attrs来进行传递。
在子组件封装时,编写:

<el-input 
    v-model="inputValue"
    v-bind="$attrs" 
>
</el-input>

当然对于你二次封装的组件,根据你的业务需要,直接固定一些属性。
这样,在父组件中,我们可以像使用el-input组件一样,使用我们自己的组件传递属性和监听事件。

<c-input ref="nameRef" class="name-input" v-model:value="addForm.name" @input="handleInput" clearable/>

三、插槽传递

对于ElementPlus中的组件,通常都会都一些插槽,那我们封装后想保留这些插槽的使用,该如何写?Vue3为我们提供了$slots,里面存着父组件所传入插槽的对象。所以我们可以这样写:

<el-input 
   ref="input"
   class="c-input" 
   v-model="inputValue" 
   :placeholder="props.label" 
   v-bind="$attrs" 
>
   <template v-for="(_, name) in $slots" v-slot:[name]>
       <slot :name="name"></slot>
   </template>
</el-input>

这样,在父组件中我们可以正常使用el-input中所带有的插槽:

<c-input v-model:value="loginForm.account" :label="$t('input.username')" clearable>
   <template #prefix>
       <el-icon><User /></el-icon>
   </template>
</c-input>

四、原组件方法获取并暴露

最后一步,在父组件中想通过绑定ref调用el-input的方法,该如何写?首先父组件直接调用肯定是不行的,因为封装的组件中并没有这些方法,这些方法是挂在封装的el-input的实例对象上的。所以,解决办法就是我们通过在子组件中获取到这些方法,然后通过defineExpose向父组件暴露就行了。
子组件:

import { ref, onMounted, defineExpose } from 'vue';
import type { InputInstance } from 'element-plus';

const input = ref<InputInstance>()
const inputMethods = ref({})

onMounted(() => {
    const refMethods = Object.entries(input.value).filter(([_, value]) => value instanceof Function)
    refMethods.forEach(([key, value]) => {
        inputMethods.value[key] = value
    })
})
defineExpose(inputMethods.value)

<el-input 
   ref="input"
   class="c-input" 
   v-model="inputValue" 
   :placeholder="props.label" 
   v-bind="$attrs" 
>
   <template v-for="(_, name) in $slots" v-slot:[name]>
       <slot :name="name"></slot>
   </template>
</el-input>

这样,父组件中获取该组件的实例对象上就会存在这些方法了。完美解决!

Vue3使用elementplus组件实现选项卡二级联动需要以下步骤: 1. 安装Element Plus组件库。可以使用npm或yarn进行安装,具体命令如下: ``` npm install element-plus --save ``` 或者 ``` yarn add element-plus ``` 2. 在Vue3项目引入Element Plus组件库,并注册所需的组件。可以在main.js文件进行全局引入和注册,具体代码如下: ``` import { createApp } from 'vue' import App from './App.vue' import ElementPlus from 'element-plus' import 'element-plus/lib/theme-chalk/index.css' const app = createApp(App) app.use(ElementPlus) app.mount('#app') ``` 3. 在Vue3模板使用el-tabs和el-tab-pane组件实现选项卡的二级联动。可以根据需求进行自定义样式和数据绑定。具体代码如下: ``` <template> <el-tabs v-model="activeName"> <el-tab-pane label="Tab 1" name="1"> <el-select v-model="select1" @change="handleChange1"> <el-option label="Option 1-1" value="1-1"></el-option> <el-option label="Option 1-2" value="1-2"></el-option> </el-select> </el-tab-pane> <el-tab-pane label="Tab 2" name="2"> <el-select v-model="select2" @change="handleChange2"> <el-option label="Option 2-1" value="2-1"></el-option> <el-option label="Option 2-2" value="2-2"></el-option> </el-select> </el-tab-pane> </el-tabs> </template> <script> export default { data() { return { activeName: '1', select1: '', select2: '' } }, methods: { handleChange1(val) { // 根据第一个下拉框的值,更新第二个下拉框的选项 if (val === '1-1') { this.select2 = '2-1' } else if (val === '1-2') { this.select2 = '2-2' } }, handleChange2(val) { // 处理第二个下拉框的选项 } } } </script> ``` 上述代码,el-tabs和el-tab-pane组件用于实现选项卡的切换,el-select组件用于实现下拉框。通过@change事件监听下拉框选项的变化,根据第一个下拉框的值更新第二个下拉框的选项。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

聂大哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值