在Vue使用$attrs實現(xiàn)構(gòu)建高級組件
這節(jié)課,我們來看下 Vue3 中的 $attrs
屬性。首先,我們會介紹它的用途以及它的實現(xiàn)與 Vue2 有哪些不兩同點,并通過事例來加深對它的理解。
真正理解了 $attrs
屬性有助于我們構(gòu)建易于使用和可擴展的高級組件
什么是 $attrs
對 $attrs
定義, Vue2 與 Vue3 是不一樣的,這里我們主要來介紹 Vue3 的版本:
$attrs 對象包含了除組件所聲明的 props 和 emits 之外的所有其他 attribute,例如 class,style,v-on 監(jiān)聽器等等。
$attrs
也可以被看作是一個安全網(wǎng),它可以捕獲任何我們沒有在組件中聲明的東西。我們考慮一個只有一個屬性和事件處理程序的組件,如下所示:
<template> ??<h1?@click="$emit('custom',?'改變標題')">{{?title?}}</h1> </template> <script> export?default?{ ??name:?'Example', ??props:?['title'], ??emits:?['custom'], } </script>
如果在父組件中像下面這樣實例化上面的組件:
<template> ??<div?id="app"> ????<SimpleEvent ??????id="myId" ??????class="myClass" ??????data-cy="cypress-testing" ??????@blur="onBlur" ??????title="測試$attrs" ??????description="沒有聲明?props" ??????@custom="onCustom" ????/> ??</div> </template> <script?setup> import?SimpleEvent?from?'./components/Button.vue' const?onBlur?=?()?=>?{ ??//?todo } const?onCustom?=?()?=>?{ ??//?todo } </script>
如果在組件中把 $attrs
打印出來,我們會得到如下內(nèi)容:
{ ??id:?'myId', ??class:?'myClass', ??'data-cy':?'cypress-testing', ??description:?'沒有聲明?props', ??onBlur:?()?=>?{?//?todo?}? }
上面這些信息,感覺沒啥用,其實不然,我們下面會介紹如何利用這些信息。
attrs V3 vs $attrs V2
這小節(jié),我們來看下 Vue2 與 Vue3 中的 attrs
屬性的區(qū)別,先來看張圖:
與 Vue2 的區(qū)別主要有:
- 自定義事件放在
@listerner
對象中 - 不包含
class
屬性
而 Vue3 中的 attrs
對象包含了除組件所聲明的 props
和 emits
之外的所有其他 attribute
,這有利于我們方便使用這些屬性。
下面我們來看些事例。
事例
首先我們創(chuàng)建一個 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)建一個 slider
,還實現(xiàn)了一個雙向綁定。然后可以像下面這樣使用該組件:
?<Slider-1?v-model="value"?/>
添加一些屬性
目前我們的 Slier 組件還很簡單,不太符合實際情況。所以,我們添加幾個屬性(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" ????/>
運行后,通過控制檢查元素,我們可以看下,我們新加的屬性都被添加到了 HTML 元素上了:
看到這里,大家可能有疑問了,既然所有的 "非屬性/事件" 屬性都已經(jīng)自動應用于內(nèi)部的HTML元素,為什么還要對 $attrs
做這么大的介紹?
添加標題和值
新增需求:作為一個滑塊的使用者,用戶希望能夠看到一個標題,以及它在屏幕上顯示的數(shù)字形式的值。
我們在調(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>
乍一看,好像沒啥問題,但如果我們仔細觀察,可以看到有些東西是不對的。
首先,Slider 不是藍色的。第二,value
遠遠超過了50,最后,檢查一下HTML,會看到我們所有的額外屬性(min, max, data-cy
)都被分配給了根元素,而不是我們的 input
元素。
解決上述問題的最好方法是找到一種方法,將所有的屬性、類、參數(shù)和事件直接 "應用" 到 input 字段上,而不需我們手動的一個個聲明。這就是 $attrs
出場的地方。
$attrs 救場
在本文的開頭,我們介紹了 $attrs
。它是一個存放所有 "未聲明"的屬性和事件的地方,而這正是我們需要解決的問題。
要使用這個功能,我們只需將 $attrs
屬性應用于一個或多個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
充當橋梁,將所有的屬性(類、屬性、屬性和自定義事件)復制到一個或多個元素上。Slider 組件又回到了正常模式上了。
還有一個問題--我們添加的屬性不僅被分配給了 input
元素上,也分配給了 root
元素。
通常情況下,這可能對界面沒啥影響,但有的屬性確實會生產(chǎn)一些副作用,下面,我們來解決這個問題。
inheritAttrs: false
默認情況下,任何被傳遞給組件的額外參數(shù)都會自動應用于根元素(以及所有有 $attrs
綁定的元素)。
為了關閉這個功能,并控制哪些元素可接受這個額外的屬性,我們可以使用一個名為 inheritAttrs
的標志,并將其設置為false
。
經(jīng)過這樣的改變,我們的HTML就變得漂亮且干凈了。所有的額外屬性都只作用于 input
元素。
以上就是在Vue使用$attrs實現(xiàn)構(gòu)建高級組件的詳細內(nèi)容,更多關于Vue $attrs構(gòu)建高級組件的資料請關注腳本之家其它相關文章!
相關文章
vue jsx 使用指南及vue.js 使用jsx語法的方法
這篇文章主要介紹了vue jsx 使用指南及vue.js 使用jsx語法的方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-11-11基于vue 實現(xiàn)表單中password輸入的顯示與隱藏功能
這篇文章主要介紹了vue 實現(xiàn)表單中password輸入的顯示與隱藏功能 ,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-07-07