vue 組件二次封裝Ui處理
vue 組件二次封裝Ui處理
在Vue開發(fā)中,我們常常需要使用UI框架提供的組件。但是UI框架的組件可能并不符合我們的需求,這時(shí)候就需要進(jìn)行二次封裝。下面是一些關(guān)于Vue組件二次封裝Ui處理的技巧:
常規(guī)時(shí)候咱們使用組件的props、events、slot等屬性的傳遞
子組件代碼:
<template>
<div class="my-input">
<el-input></el-input>
</div>
</template>
<script setup>
export default {
props:[]
}
</script>
<style scoped>
.my-input {
transition: 0.3s;
}
.my-input:hover,
.my-input:focus-within {
filter: drop-shadow(0 0 3px rgba(0, 0, 0, 0.3));
}
</style>
父組件使用:
<my-input v-model="value"></my-input>
如果使用props接收弊端:
- 基本上組件不會(huì)只有一兩個(gè)屬性,屬性多的話接收的數(shù)據(jù)量多,需要寫大量的無用代碼
- 如果存在多級(jí)組件嵌套傳值,又是重復(fù)代碼,并且維護(hù)性差
$attrs 和$listeners 解決數(shù)據(jù)穿透問題
因?yàn)関ue2和vue3有些不同咱分開講:
vue2的介紹和使用:
上面感覺很難懂:簡(jiǎn)單來說就是**$attrs
** 接收傳遞過來的props的值。**$listeners
** 當(dāng) inheritAttrs:true 繼承除props之外的所有屬性;inheritAttrs:false 只繼承class屬性
vue2的代碼:
father.vue 組件:
<template>
<child :name="name" :age="age" :infoObj="infoObj" @updateInfo="updateInfo" @delInfo="TodelInfo" />
</template>
<script>
import Child from '../components/child.vue'
export default {
name: 'father',
components: { Child },
data () {
return {
name: 'zhangyangguang',
age: 24,
infoObj: {
from: '濟(jì)南',
job: 'policeman',
hobby: ['reading', 'writing', 'skating']
}
}
},
methods: {
updateInfo() {
console.log('update info');
},
TodelInfo() {
console.log('delete info');
}
}
}
</script>
child.vue 組件:
<template>
<son :height="height" :weight="weight" @addInfo="addInfo" v-bind="$attrs" v-on="$listeners" />
// 通過 $listeners 將父作用域中的事件,傳入 grandSon 組件,使其可以獲取到 father 中的事件
</template>
<script>
import Son from '../components/Son.vue'
export default {
name: 'child',
components: { Son },
props: ['name'],
data() {
return {
height: '183cm',
weight: '76kg'
};
},
created() {
console.log(this.$attrs);
// 結(jié)果:age, infoObj, 因?yàn)楦附M件共傳來name, age, infoObj三個(gè)值,由于name被 props接收了,所以只有age, infoObj屬性
console.log(this.$listeners); // updateInfo: f, TodelInfo: f
},
methods: {
addInfo () {
console.log('add info')
}
}
}
</script>
son.vue 組件:
<template>
<div>
{{ $attrs }} --- {{ $listeners }}
<div>
</template>
<script>
export default {
... ...
props: ['weight'],
created() {
console.log(this.$attrs); // age, infoObj, height
console.log(this.$listeners) // updateInfo: f, TodelInfo: f, addInfo: f
this.$emit('updateInfo') // 可以觸發(fā) father 組件中的updateInfo函數(shù)
}
}
</script>
一般不常用,可讀性不是很好。但是組件嵌套層比較深,props很繁瑣,可以使用。
vue3的使用和介紹:
代碼:
<template>
<div class="my-input">
<el-input v-bind="$attrs"></el-input>
</div>
</template>
<script setup></script>
<style scoped>
.my-input {
transition: 0.3s;
}
.my-input:hover,
.my-input:focus-within {
filter: drop-shadow(0 0 3px rgba(0, 0, 0, 0.3));
}
</style>
直接 通過**$attrs
** 接收屬性和方法。后面在詳細(xì)介紹vue3的Attributes
這樣到這里已經(jīng)解決屬性和方法的問題了。
解決傳值和方法問題,還有一個(gè)slot插槽
比如elementPlus的input 有如下插槽:
初步解決方法:
封裝組件里定義對(duì)應(yīng)數(shù)量的插槽然后再次傳遞
<template>
<div class="my-input">
<el-input v-bind="$attrs">
<template #prefix>
<slot name="prefix"></slot>
</template>
<template #suffix>
<slot name="suffix"></slot>
</template>
<template #prepend>
<slot name="prepend"></slot>
</template>
<template #append>
<slot name="append"></slot>
</template>
</el-input>
</div>
</template>
<script setup></script>
<style scoped>
.my-input {
transition: 0.3s;
}
.my-input:hover,
.my-input:focus-within {
filter: drop-shadow(0 0 3px rgba(0, 0, 0, 0.3));
}
</style>
這里定義了四個(gè)插槽然后再次傳遞,確實(shí)解決了插槽問題。但是使用的組件不一定會(huì)使用全部的插槽。如果使用一個(gè)那咱們封裝的組件就把其他插槽給傳遞了過去。這樣很不保險(xiǎn),并且也不對(duì)
解決思路:父級(jí)傳遞幾個(gè)插槽,咱就傳遞幾個(gè)給子組件,不全部傳遞
進(jìn)階解決方法:使用$slots
也就是說**$slots**可以獲取父級(jí)組件傳遞的插槽。
vue3代碼:
<template>
<div class="my-input">
<el-input v-bind="$attrs">
<template v-for="(val, name) in $slots" #[name]="slotData">
<slot :name="name" v-bind="slotData || {}"></slot>
</template>
</el-input>
</div>
</template>
<script>
export default {
created() {
console.log(this.$slots);
},
};
</script>
<style scoped>
.my-input {
transition: 0.3s;
}
.my-input:hover,
.my-input:focus-within {
filter: drop-shadow(0 0 3px rgba(0, 0, 0, 0.3));
}
</style>
這樣就是父級(jí)傳遞啥那就傳遞啥插槽。到此解決了插槽問題。
到這里還有個(gè)最難的**ref 問題:**
因?yàn)閞ef只能作用于當(dāng)前無法作用到孫組件
對(duì)于ref傳遞問題vue無法解決。但是咱可以換一個(gè)思路。使用ref無非是為了使用孫組件暴露的一些方法。那咱就可以吧孫組件的方法提取到子組件
說白了吧孫組件的方法提取到當(dāng)前實(shí)例
代碼:
<template>
<div class="my-input">
<el-input ref="inp" v-bind="$attrs">
<template v-for="(val, name) in $slots" #[name]="slotData">
<slot :name="name" v-bind="slotData || {}"></slot>
</template>
</el-input>
</div>
</template>
<script>
export default {
created() {
console.log(this.$slots);
},
mounted() {
console.log(this.$refs.inp);
const entries = Object.entries(this.$refs.inp);
for (const [key, value] of entries) {
this[key] = value;
}
},
};
</script>
<style scoped>
.my-input {
transition: 0.3s;
}
.my-input:hover,
.my-input:focus-within {
filter: drop-shadow(0 0 3px rgba(0, 0, 0, 0.3));
}
</style>
這樣就完美解決了組件的Ui封裝。文章來源:http://www.zghlxwxcb.cn/news/detail-413336.html
以上是一些關(guān)于Vue組件二次封裝Ui處理的技巧。通過二次封裝,我們可以更好地滿足我們的需求,提高開發(fā)效率。文章來源地址http://www.zghlxwxcb.cn/news/detail-413336.html
到了這里,關(guān)于vue3組件二次封裝Ui處理的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!