vue3 $attrs和inheritAttrs的用法說(shuō)明
$attrs和inheritAttrs用法
$attrs
屬性解釋?zhuān)喊烁缸饔糜蛑胁蛔鳛榻M件 props 或自定義事件的 attribute 綁定和事件。當(dāng)一個(gè)組件沒(méi)有聲明任何prop 時(shí),這里會(huì)包含所有父作用域的綁定,并且可以通過(guò) v-bind="$attrs" 傳入內(nèi)部組件——這在創(chuàng)建高階的組件時(shí)會(huì)非常有用。inheritAttrs
屬性解釋?zhuān)喝绻悴幌MM件的根元素繼承特性,你可以在組件的選項(xiàng)中設(shè)置 inheritAttrs: false
可能不是很好理解,我們可以舉個(gè)例子來(lái)驗(yàn)證一下。
在父組件app.vue中
<template> ? <div> ? ? <MyInput type="text" placeholder="輸入用戶(hù)名" v-model="state.text" /> ? ? <MyInput type="password" placeholder="輸入密碼" ?v-model="state.pass" ?/> ? </div> </template>
<script setup> import MyInput from "@/components/myInput.vue"; import { reactive } from "vue"; const state = reactive({ ? text: "", ? pass: "", }); </script>
子組件 myInput.vue 設(shè)置 inheritAttrs: true(默認(rèn))
<template> ? <div class="input"> ? ? <input v-bind="$attrs" v-model="modelValue" /> ? </div> </template>
<script> export default { ? props: { ? ? modelValue: [String, Number], ? }, }; </script>
子組件 myInput.vue 設(shè)置 inheritAttrs: false
<template> ? <div class="input"> ? ? <input v-bind="$attrs" v-model="modelValue"/> ? </div> </template>
<script> export default { ? inheritAttrs: false, ? props: { ? ? modelValue: [String, Number], ? }, }; </script>
小結(jié):
由上述例子可以看出,子組件的props中未注冊(cè)父組件傳遞過(guò)來(lái)的屬性。
- 當(dāng)設(shè)置inheritAttrs:true時(shí),子組件的頂層標(biāo)簽元素中會(huì)渲染出父組件傳遞過(guò)來(lái)的屬性(例如:type="text"等)
- 當(dāng)設(shè)置inheritAttrs: false時(shí),子組件的頂層標(biāo)簽元素中不會(huì)渲染出父組件傳遞過(guò)來(lái)的屬性
- 不管inheritAttrs為true或者false,子組件中都能通過(guò)$attrs屬性獲取到父組件中傳遞過(guò)來(lái)的屬性。
$attrs和inheritAttrs實(shí)例
官網(wǎng)的文檔簡(jiǎn)短而又不清晰,實(shí)在是看不懂,只好自己找代碼驗(yàn)證來(lái)看看是什么意思:
<!DOCTYPE html> <html lang="en"> ? <head> ? ? <meta charset="UTF-8"> ? ? <meta name="viewport" content="width=device-width, initial-scale=1.0"> ? ? <title>Document</title> ? ? <script src="https://cdn.bootcdn.net/ajax/libs/vue/3.1.5/vue.global.js"></script> </head> ? <body> ? ? <div id="app"> ? ? ? ? <father :v1="'value1'" :v2="'value2'" :v3="'value3'"></father> ? ? </div> </body> ? </html>
<script> const app = Vue.createApp({ data() { return {} }, }) app.component('father', { // inheritAttrs: false, props: ['v1'], template: ` <div><p>v1 is {{v1}}</p> <son v-bind='$attrs' :some="1"></son> </div>`, created() { console.log('father:', this.$attrs) } }) app.component('son', { // inheritAttrs: false, props: ['v2'], template: `<div><p>v2 is {{v2}}</p> <grandSon v-bind='$attrs'></grandSon> </div>`, created() { console.log('son:', this.$attrs) } }) app.component('grandSon', { props: ['v3'], template: `<p>v3 is {{v3}}</p>`, created() { console.log('grandSon:', this.$attrs) } }) app.mount('#app') </script>
頁(yè)面顯示的結(jié)果:
v1 is value1
v2 is value2
v3 is value3
頁(yè)面源代碼:
<div id="app" data-v-app=""> ? ?<div v2="value2" v3="value3"> <!-- 這是father --> ? ? ? <p>v1 is value1</p> ? ? ? <div v3="value3" some="1"> ?<!-- 這是 son--> ? ? ? ? ? <p>v2 is value2</p> ? ? ? ? ? ?<p some="1">v3 is value3</p> ?<!-- 這是 grandSon --> ? ? ? </div> ? ?</div> </div>
控制臺(tái)打印是當(dāng)前組件的$attrs:
father: Proxy {v2: "value2", v3: "value3", __vInternal: 1}
son: Proxy {v3: "value3", some: 1, __vInternal: 1}
grandSon: Proxy {some: 1, __vInternal: 1}
首選,father組件被傳入了3個(gè)值,但是實(shí)際使用props接收的只有v1,v2和v3作為attributes在DOM里面渲染了。
上圖的devtool 也可以說(shuō)明,另外就是控制臺(tái)也同時(shí)證明了。
同樣son組件只是接收v2作為prop:
grandSon組件只是接收v3作為prop
father prop:v1,attributes: v2,v3
son prop:v2 ,attributes:v3,some
grandSon prop:v3,,attributes: some
發(fā)現(xiàn)無(wú)論是father傳入的3個(gè)值v1,v2,v3還是son又傳入的值':some=1',
只要不被prop傳入下一層組件,那么一定是在下一層組件的$attrs,也就是說(shuō)不被作為prop的值會(huì)傳入下一個(gè)組件作為attrs的一員。一個(gè)組件的attrs由父組件傳遞以及自己自帶的組合而成。
上面說(shuō)的是$attrs,那么inheritAttrs則說(shuō)的是attrs繼承,這里的繼承是控制DOM渲染,不繼承也就是不渲染了,但是實(shí)際還是存在這個(gè)attrs的。
`inheritAttrs`屬性默認(rèn)是true,所以能看到上面的結(jié)論,attrs會(huì)往下傳,當(dāng)設(shè)置為false的時(shí)候就不會(huì)在DOM渲染從上一層繼承來(lái)的attrs。
修改一下代碼:
app.component('father', { inheritAttrs: false, // 不繼承 props: ['v1'], template: ` <div><p>v1 is {{v1}}</p> <son v-bind='$attrs' :some="1"></son> </div>`, created() { console.log('father:', this.$attrs) } })
father組件這不繼承attrs,控制臺(tái)的打印沒(méi)變:
father: Proxy {v2: "value2", v3: "value3", __vInternal: 1}
son: Proxy {v3: "value3", some: 1, __vInternal: 1}
grandSon: Proxy {some: 1, __vInternal: 1}
devtool這里依然可以看到attrs
但是看源代碼:
<div id="app" data-v-app=""> ? <div> ? ? ? ? ? ? ? ? ? ? ? ? ?<!-- 這里是 father --> <!-- 看這行 --> ? ? <p>v1 is value1</p> ? ? <div v3="value3" some="1"> ? ? <!-- 這里是 son--> ? ? ? <p>v2 is value2</p> ? ? ? <p some="1">v3 is value3</p> ? <!-- 這里是 grandSon--> ? ? ? </div> ? ? </div> </div>
DOM渲染里面的v2,v3 attrs都不存在了。
所以綜合總結(jié)一下:
$attrs就是給組件傳值排除了作為prop的那部分(比如father的v2,v3),包括了(class,id)inheritAttrs只是用來(lái)控制attrs是否在DOM中渲染。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Vue實(shí)現(xiàn)點(diǎn)擊按鈕復(fù)制文本內(nèi)容的例子
今天小編就為大家分享一篇Vue實(shí)現(xiàn)點(diǎn)擊按鈕復(fù)制文本內(nèi)容的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-11-11vue與vue-i18n結(jié)合實(shí)現(xiàn)后臺(tái)數(shù)據(jù)的多語(yǔ)言切換方法
下面小編就為大家分享一篇vue與vue-i18n結(jié)合實(shí)現(xiàn)后臺(tái)數(shù)據(jù)的多語(yǔ)言切換方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-03-03關(guān)于Vue中過(guò)濾器的必懂小知識(shí)
vue過(guò)濾器可以在不改變?cè)紨?shù)據(jù),只是對(duì)數(shù)據(jù)進(jìn)行加工處理后返回過(guò)濾后的數(shù)據(jù)再進(jìn)行調(diào)用處理,下面這篇文章主要給大家介紹了關(guān)于Vue中過(guò)濾器必懂小知識(shí)的相關(guān)資料,需要的朋友可以參考下2021-10-10Vue實(shí)現(xiàn)動(dòng)態(tài)圓環(huán)百分比進(jìn)度條
這篇文章主要為大家詳細(xì)介紹了Vue實(shí)現(xiàn)動(dòng)態(tài)圓環(huán)百分比進(jìn)度條,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09vue配置nprogress實(shí)現(xiàn)頁(yè)面頂部進(jìn)度條
這篇文章主要為大家詳細(xì)介紹了vue配置nprogress實(shí)現(xiàn)頁(yè)面頂部進(jìn)度條,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-09-09vue3自定義組件之v-model實(shí)現(xiàn)父子組件雙向綁定
這篇文章主要介紹了vue3自定義組件之v-model實(shí)現(xiàn)父子組件雙向綁定方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08在vue中給列表中的奇數(shù)行添加class的實(shí)現(xiàn)方法
今天小編就為大家分享一篇在vue中給列表中的奇數(shù)行添加class的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09vue計(jì)時(shí)器的實(shí)現(xiàn)方法
這篇文章主要為大家詳細(xì)介紹了vue計(jì)時(shí)器的實(shí)現(xiàn)方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06