在Vue使用$attrs實(shí)現(xiàn)構(gòu)建高級(jí)組件
這節(jié)課,我們來(lái)看下 Vue3 中的 $attrs 屬性。首先,我們會(huì)介紹它的用途以及它的實(shí)現(xiàn)與 Vue2 有哪些不兩同點(diǎn),并通過(guò)事例來(lái)加深對(duì)它的理解。
真正理解了 $attrs 屬性有助于我們構(gòu)建易于使用和可擴(kuò)展的高級(jí)組件
什么是 $attrs
對(duì) $attrs 定義, Vue2 與 Vue3 是不一樣的,這里我們主要來(lái)介紹 Vue3 的版本:
$attrs 對(duì)象包含了除組件所聲明的 props 和 emits 之外的所有其他 attribute,例如 class,style,v-on 監(jiān)聽(tīng)器等等。
$attrs 也可以被看作是一個(gè)安全網(wǎng),它可以捕獲任何我們沒(méi)有在組件中聲明的東西。我們考慮一個(gè)只有一個(gè)屬性和事件處理程序的組件,如下所示:
<template>
??<h1?@click="$emit('custom',?'改變標(biāo)題')">{{?title?}}</h1>
</template>
<script>
export?default?{
??name:?'Example',
??props:?['title'],
??emits:?['custom'],
}
</script>
如果在父組件中像下面這樣實(shí)例化上面的組件:
<template>
??<div?id="app">
????<SimpleEvent
??????id="myId"
??????class="myClass"
??????data-cy="cypress-testing"
??????@blur="onBlur"
??????title="測(cè)試$attrs"
??????description="沒(méi)有聲明?props"
??????@custom="onCustom"
????/>
??</div>
</template>
<script?setup>
import?SimpleEvent?from?'./components/Button.vue'
const?onBlur?=?()?=>?{
??//?todo
}
const?onCustom?=?()?=>?{
??//?todo
}
</script>如果在組件中把 $attrs 打印出來(lái),我們會(huì)得到如下內(nèi)容:
{
??id:?'myId',
??class:?'myClass',
??'data-cy':?'cypress-testing',
??description:?'沒(méi)有聲明?props',
??onBlur:?()?=>?{?//?todo?}?
}
上面這些信息,感覺(jué)沒(méi)啥用,其實(shí)不然,我們下面會(huì)介紹如何利用這些信息。
attrs V3 vs $attrs V2
這小節(jié),我們來(lái)看下 Vue2 與 Vue3 中的 attrs 屬性的區(qū)別,先來(lái)看張圖:

與 Vue2 的區(qū)別主要有:
- 自定義事件放在
@listerner對(duì)象中 - 不包含
class屬性
而 Vue3 中的 attrs 對(duì)象包含了除組件所聲明的 props 和 emits 之外的所有其他 attribute,這有利于我們方便使用這些屬性。
下面我們來(lái)看些事例。
事例
首先我們創(chuàng)建一個(gè) Slider 組件,內(nèi)容如下所示:
<template>
??<input?
????type="range"??
????:value="modelValue"
????@input="$emit('update:modelValue',?$event.target.value)"
????class="slider__input"?/>
</template>
<script>
export?default?{
??name:?"Slider-1",
??props:?{
????modelValue:?[Number,?String],
??}
};
</script>
<style?lang="scss">
//?這里省略一堆樣式,自行看事例
</style>
上面代碼我們創(chuàng)建一個(gè) slider,還實(shí)現(xiàn)了一個(gè)雙向綁定。然后可以像下面這樣使用該組件:
?<Slider-1?v-model="value"?/>

添加一些屬性
目前我們的 Slier 組件還很簡(jiǎn)單,不太符合實(shí)際情況。所以,我們添加幾個(gè)屬性(min, max, class, id, data-cy, @keydown 和 aria-label)。
??<Slider-1 ??????v-model="value" ??????min="0" ??????max="50" ??????class="blue_slider" ??????id="special_id" ??????data-cy="cypress-slider" ??????@keydown="()?=>?true" ??????aria-label="Example?slider" ????/>
運(yùn)行后,通過(guò)控制檢查元素,我們可以看下,我們新加的屬性都被添加到了 HTML 元素上了:

看到這里,大家可能有疑問(wèn)了,既然所有的 "非屬性/事件" 屬性都已經(jīng)自動(dòng)應(yīng)用于內(nèi)部的HTML元素,為什么還要對(duì) $attrs 做這么大的介紹?
添加標(biāo)題和值
新增需求:作為一個(gè)滑塊的使用者,用戶(hù)希望能夠看到一個(gè)標(biāo)題,以及它在屏幕上顯示的數(shù)字形式的值。
我們?cè)谡{(diào)整一下 Slider 組件,內(nèi)容如下:
//?Slider-2.vue
<template>
??<div?class="slider">
????<h1>{{?title?}}</h1>
????<input?
??????type="range"?
??????:value="modelValue"
??????@input="$emit('update:modelValue',?$event.target.value)"
??????class="slider__input"?/>
??????<div>Value:?{{?value?}}</div>
??</div>
</template>
<script>
export?default?{
??name:?"Slider-2",
??props:?{
????modelValue:?[Number,?String]
????title:?[String],
????value:?[Number,?String],
??}
};
</script>

乍一看,好像沒(méi)啥問(wèn)題,但如果我們仔細(xì)觀(guān)察,可以看到有些東西是不對(duì)的。
首先,Slider 不是藍(lán)色的。第二,value 遠(yuǎn)遠(yuǎn)超過(guò)了50,最后,檢查一下HTML,會(huì)看到我們所有的額外屬性(min, max, data-cy)都被分配給了根元素,而不是我們的 input 元素。
解決上述問(wèn)題的最好方法是找到一種方法,將所有的屬性、類(lèi)、參數(shù)和事件直接 "應(yīng)用" 到 input 字段上,而不需我們手動(dòng)的一個(gè)個(gè)聲明。這就是 $attrs 出場(chǎng)的地方。
$attrs 救場(chǎng)
在本文的開(kāi)頭,我們介紹了 $attrs。它是一個(gè)存放所有 "未聲明"的屬性和事件的地方,而這正是我們需要解決的問(wèn)題。
要使用這個(gè)功能,我們只需將 $attrs 屬性應(yīng)用于一個(gè)或多個(gè)HTML元素,使用 v-bind 操作符。
<template>
??<div?class="slider">
????<h1>{{?title?}}</h1>
????<input?
??????type="range"??
??????v-bind="$attrs"
??????:value="modelValue"
??????@input="$emit('update:modelValue',?$event.target.value)"
??????class="slider__input"?/>
??????<div>Value:?{{?modelValue?}}</div>
??</div>
</template>
在組件中,我們使用 attrs 充當(dāng)橋梁,將所有的屬性(類(lèi)、屬性、屬性和自定義事件)復(fù)制到一個(gè)或多個(gè)元素上。Slider 組件又回到了正常模式上了。

還有一個(gè)問(wèn)題--我們添加的屬性不僅被分配給了 input 元素上,也分配給了 root元素。
通常情況下,這可能對(duì)界面沒(méi)啥影響,但有的屬性確實(shí)會(huì)生產(chǎn)一些副作用,下面,我們來(lái)解決這個(gè)問(wèn)題。
inheritAttrs: false
默認(rèn)情況下,任何被傳遞給組件的額外參數(shù)都會(huì)自動(dòng)應(yīng)用于根元素(以及所有有 $attrs 綁定的元素)。
為了關(guān)閉這個(gè)功能,并控制哪些元素可接受這個(gè)額外的屬性,我們可以使用一個(gè)名為 inheritAttrs 的標(biāo)志,并將其設(shè)置為false。
經(jīng)過(guò)這樣的改變,我們的HTML就變得漂亮且干凈了。所有的額外屬性都只作用于 input 元素。
以上就是在Vue使用$attrs實(shí)現(xiàn)構(gòu)建高級(jí)組件的詳細(xì)內(nèi)容,更多關(guān)于Vue $attrs構(gòu)建高級(jí)組件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue jsx 使用指南及vue.js 使用jsx語(yǔ)法的方法
這篇文章主要介紹了vue jsx 使用指南及vue.js 使用jsx語(yǔ)法的方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-11-11
基于vue 實(shí)現(xiàn)表單中password輸入的顯示與隱藏功能
這篇文章主要介紹了vue 實(shí)現(xiàn)表單中password輸入的顯示與隱藏功能 ,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-07-07
VUE中鼠標(biāo)滾輪使div左右滾動(dòng)的方法詳解
這篇文章主要給大家介紹了關(guān)于VUE中鼠標(biāo)滾輪使div左右滾動(dòng)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12
vue3封裝數(shù)字滾動(dòng)組件的實(shí)現(xiàn)示例
本文主要介紹了vue3封裝數(shù)字滾動(dòng)組件的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-08-08

