vm.$attrs 【Vue 2.4.0新增inheritAttrs,attrs詳解】

1、vm.$attrs簡(jiǎn)介

首先我們來(lái)看下vue官方對(duì)vm.$attrs的介紹:
包含了父作用域中不作為 prop 被識(shí)別 (且獲取) 的特性綁定 (class 和 style 除外)。當(dāng)一個(gè)組件沒(méi)有聲明任何 prop 時(shí),這里會(huì)包含所有父作用域的綁定 (class 和 style 除外)憔古,并且可以通過(guò) v-bind="$attrs" 傳入內(nèi)部組件——在創(chuàng)建更高層次的組件時(shí)非常有用。
猛一看有點(diǎn)看不明白....

2淋袖、場(chǎng)景介紹

vue中一個(gè)比較令人煩惱的事情是屬性只能從父組件傳遞給子組件鸿市。這也就意味著當(dāng)你想向嵌套層級(jí)比較深組件數(shù)據(jù)傳遞,只能由父組件傳遞給子組件即碗,子組件再傳遞給孫子組件...像下面這樣:

<parent-component :passdown="passdown">

<child-component :passdown="passdown">

<grand-child-component :passdown="passdown">

....

就這樣一層一層的往下傳遞passdown這個(gè)變量焰情,最后才能用{{passdown}}。

假如我們需要傳遞的屬性只有1,2個(gè)還行拜姿,但是如果我們要傳遞的有幾個(gè)或者10來(lái)個(gè)的情況烙样,這會(huì)是什么樣的場(chǎng)景,我們會(huì)在每個(gè)組件不停的props蕊肥,每個(gè)必須寫(xiě)很多遍谒获。有沒(méi)有其它方便的寫(xiě)法?有壁却,通過(guò)vuex的父子組件通信批狱,的確這個(gè)是一個(gè)方法,但是還有其它的方法展东,這個(gè)就是我們要說(shuō)的赔硫。通過(guò)inheritAttrs選項(xiàng),以及實(shí)例屬性$attrs

3盐肃、實(shí)例:

<template>
  <div class="home">
    <mytest  :title="title" :massgae="massgae"></mytest>
  </div>
</template>
<script>
export default {
  name: 'home',
  data () {
    return {
      title:'title1111',
      massgae:'message111'
    }
  },
  components:{
    'mytest':{
      template:`<div>這是個(gè)h1標(biāo)題{{title}}</div>`,
      props:['title'],
      data(){
        return{
          mag:'111'
        }
      },
      created:function(){
        console.log(this.$attrs)//注意這里
      }
    }
  }
}
</script>

上邊的代碼爪膊,我們?cè)诮M件里只是用了title這個(gè)屬性权悟,massgae屬性我么是沒(méi)有用的,那么下瀏覽器渲染出來(lái)是什么樣呢推盛?如下圖:


attrs.png

我們看到:組件內(nèi)未被注冊(cè)的屬性將作為普通html元素屬性被渲染峦阁,如果想讓屬性能夠向下傳遞,即使prop組件沒(méi)有被使用耘成,你也需要在組件上注冊(cè)榔昔。這樣做會(huì)使組件預(yù)期功能變得模糊不清,同時(shí)也難以維護(hù)組件的DRY瘪菌。在Vue2.4.0,可以在組件定義中添加inheritAttrs:false撒会,組件將不會(huì)把未被注冊(cè)的props呈現(xiàn)為普通的HTML屬性。但是在組件里我們可以通過(guò)其$attrs可以獲取到?jīng)]有使用的注冊(cè)屬性师妙,如果需要诵肛,我們?cè)谶@也可以往下繼續(xù)傳遞。

如果我們?cè)谧咏M件里設(shè)置 inheritAttrs: false:

components:{
    'mytest':{
      template:`<div>這是個(gè)h1標(biāo)題{{title}}</div>`,
      props:['title'],
      inheritAttrs: false,
      data(){
        return{
          mag:'111'
        }
      },
      created:function(){
        console.log(this.$attrs)//注意這里
      }
    }

渲染效果如下:


不繼承的情況.png

補(bǔ)充:說(shuō)一下$attrs的使用

有一個(gè)頁(yè)面由父組件默穴,子組件曾掂,孫子組件構(gòu)成,如下:

<template>
    <div style="padding:50px;">
        <childcom :name="name" :age="age" :sex="sex"></childcom>
    </div>
</template>
<script>
export default {
    'name':'test',
    props:[],
    data(){
        return {
            'name':'張三',
            'age':'30',
            'sex':'男'
        }
    },
    components:{
        'childcom':{
            template:`<div>
                <div>{{name}}</div>
                <grandcom v-bind="$attrs"></grandcom>
            </div>`,
            props:['name'],
            components: {
                'grandcom':{
                    template:`<div>{{$attrs}}</div>`,
                }
            }
        }
    }
}
</script>

上面的代碼在頁(yè)面的效果是如下圖


attrs.png

如果attrs被綁定在子組件childcom上后壁顶,我們就可以在孫子組件grandcom里獲取到this.$attrs的值。這個(gè){{$attrs}}的值是父組件中傳遞下來(lái)的props(除了子組件childcom組件中props聲明的)溜歪。

記住孫子組件grandcom里獲取到this.$attrs的值是除了子組件childcom聲明的元素若专!記住是除了子組件childcom聲明的元素!例如上面的代碼我在子組件childcom組件的props里聲明了name蝴猪,那么我在孫子組件grandcom里獲取到的$attrs就不包含name屬性调衰,那么this.$attrs = { 'age':'30', 'sex':'男'}。

說(shuō)一下$attrs的優(yōu)勢(shì)到底在哪

假如我們要做一個(gè)頁(yè)面自阱,有父組件嚎莉,子組件,孫子組件沛豌,如下:

<template>
    <div>
        <childcom></childcom>
    </div>
</template>
<script>
export default {
    'name':'test',
    props:[],
    data(){
        return {
            'name':'張三',
            'age':'30',
            'sex':'男'
        }
    },
    components:{
        'childcom':{
            template:`<div>
                <div>我是子組件</div>
                <grandcom></grandcom>
            </div>`,
            components: {
                'grandcom':{
                    template:`<div>我是孫子組件</div>`,
                }
            }
        }
    }
}
</script>

如上代碼趋箩,假如我想在子組件想獲取到父組件的name屬性值,在孫子組件獲取父組件的age屬性值加派,用props的話(huà)就必須在父組件把name和age的值通過(guò)props傳遞到子組件叫确,子組件在通過(guò)props把a(bǔ)ge的值傳遞到孫子組件,到這里看明白了吧芍锦,孫子組件需要的age在子組件里沒(méi)有用到竹勉,但是為了能讓孫子組件獲取到,你必須從父組件 傳到子組件娄琉,在在子組件傳遞到孫子組件次乓。

但是用$attrs就不用那么麻煩吓歇,如下:

<template>
    <div>
        <childcom :name="name" :age="age" :sex="sex"></childcom>
    </div>
</template>
<script>
export default {
    'name':'test',
    props:[],
    data(){
        return {
            'name':'張三',
            'age':'30',
            'sex':'男'
        }
    },
    components:{
        'childcom':{
            props:['name'],
            template:`<div>
                <div>我是子組件   {{name}}</div>
                <grandcom v-bind="$attrs"></grandcom>
            </div>`,
            components: {
                'grandcom':{
                    template:`<div>我是孫子組件{{$attrs.age}}</div>`,
                }
            }
        }
    }
}
</script>

子組件綁定了"$attrs",孫子組件就能獲取到除了name屬性外所有由父組件傳遞下來(lái)的屬性票腰。如果孫子組件也想獲取到name屬性那么城看,在綁定個(gè)name如下,

 <grandcom v-bind="$attrs" :name="name"></grandcom>

細(xì)細(xì)體會(huì)下是不是這個(gè)道理丧慈。實(shí)在不行的話(huà)敲一敲代碼自己試驗(yàn)下析命,你就會(huì)豁然開(kāi)朗。

補(bǔ)充一下:inheritAttrs屬性

關(guān)于inheritAttrs這個(gè)屬性跟獲取到$attrs的值沒(méi)有關(guān)系逃默,inheritAttrs通常在編寫(xiě)基礎(chǔ)組件時(shí)候會(huì)用到鹃愤。官網(wǎng)原話(huà):默認(rèn)情況下父作用域的不被認(rèn)作 props 的特性綁定 (attribute bindings) 將會(huì)“回退”且作為普通的 HTML 特性應(yīng)用在子組件的根元素上。當(dāng)撰寫(xiě)包裹一個(gè)目標(biāo)元素或另一個(gè)組件的組件時(shí)完域,這可能不會(huì)總是符合預(yù)期行為软吐。通過(guò)設(shè)置 inheritAttrs 到 false,這些默認(rèn)行為將會(huì)被去掉吟税。而通過(guò) (同樣是 2.4 新增的) 實(shí)例屬性 $attrs 可以讓這些特性生效凹耙,且可以通過(guò) v-bind 顯性的綁定到非根元素上。

注意:這個(gè)選項(xiàng)不影響 class 和 style 綁定肠仪。

在Vue2.4.0之前版本肖抱,組件內(nèi)未被注冊(cè)的屬性將作為普通html元素屬性被渲染。

inheritAttrs到底有啥用异旧?到底用在哪里意述?看下邊代碼,

<template>
    <childcom :name="name" :age="age" type="text"></childcom>
</template>
<script>
export default {
    'name':'test',
    props:[],
    data(){
        return {
            'name':'張三',
            'age':'30',
            'sex':'男'
        }
    },
    components:{
        'childcom':{
            props:['name','age'],
            template:`<input type="number" style="border:1px solid blue">`,
        }
    }
}
</script>

上面代碼你覺(jué)得input上會(huì)怎么顯示吮蛹? 父組件傳遞了type="text"荤崇,子組件里input 上type="number",那渲染到頁(yè)面會(huì)是什么樣潮针?渲染圖如下:


默認(rèn)情況.png

看到?jīng)]术荤,父組件傳遞的type="text"覆蓋了input 上type="number",這豈不是把我的input數(shù)據(jù)類(lèi)型都給改變了每篷,這豈不是有問(wèn)題瓣戚,這不是我想要的!vㄈ痢4怠!看到這里明白了嗎吨灭?回頭去體會(huì)下上面官網(wǎng)的原話(huà)8照铡!喧兄!

需求:我需要input 上type="number"類(lèi)型不變无畔,但是我還是要取到父組件的type="text"的值啊楚,那么代碼如下:

<template>
    <childcom :name="name" :age="age" type="text"></childcom>
</template>
<script>
export default {
    'name':'test',
    props:[],
    data(){
        return {
            'name':'張三',
            'age':'30',
            'sex':'男'
        }
    },
    components:{
        'childcom':{
            inheritAttrs:false,
            props:['name','age'],
            template:`<input type="number" style="border:1px solid blue">`,
            created () {
                console.log(this.$attrs.type)
            }
        }
    }
}
</script>

頁(yè)面渲染圖如下:


需求.png

到這,我想大家都明白了inheritAttrs的作用了吧浑彰。默認(rèn)情況下vue會(huì)把父作用域的不被認(rèn)作 props 的特性綁定 且作為普通的 HTML 特性應(yīng)用在子組件的根元素上恭理。綁定就綁定,顯示就顯示郭变,沒(méi)啥大不了的颜价,但是怕就怕遇到一些特殊的,就比如上面的input的情況诉濒,這個(gè)時(shí)候inheritAttrs:false的作用就出來(lái)啦周伦。

順道補(bǔ)充一下:$listeners

父組件-子組件-孫子組件,未荒,专挪,,現(xiàn)在我要你在孫子組件里改變父組件的值片排,怎么改寨腔?有很多方法啦,但是$listeners給我們提供了一個(gè)新的思路率寡。話(huà)不多說(shuō)迫卢,直接上代碼

<template>
    <div>
        <childcom :name="name" :age="age" :sex="sex" @testChangeName="changeName"></childcom>
    </div>
</template>
<script>
export default {
    'name':'test',
    props:[],
    data(){
        return {
            'name':'張三',
            'age':'30',
            'sex':'男'
        }
    },
    components:{
        'childcom':{
            props:['name'],
            template:`<div>
                <div>我是子組件   {{name}}</div>
                <grandcom v-bind="$attrs" v-on="$listeners"></grandcom>
            </div>`,
           
            components: {
                'grandcom':{
                    template:`<div>我是孫子組件-------<button @click="grandChangeName">改變名字</button></div>`,
                    methods:{
                        grandChangeName(){
                           this.$emit('testChangeName','kkkkkk')
                        }
                    }
                }
            }
        }
    },
    methods:{
        changeName(val){
            this.name = val
        }
    }
}
</script>

頁(yè)面渲染如下:


$listers.png

$listeners可以讓你在孫子組件改變父組件的值,是不是很方便............

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末冶共,一起剝皮案震驚了整個(gè)濱河市靖避,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌比默,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盆犁,死亡現(xiàn)場(chǎng)離奇詭異命咐,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)谐岁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)醋奠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人伊佃,你說(shuō)我怎么就攤上這事窜司。” “怎么了航揉?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵塞祈,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我帅涂,道長(zhǎng)议薪,這世上最難降的妖魔是什么尤蛮? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮斯议,結(jié)果婚禮上产捞,老公的妹妹穿的比我還像新娘。我一直安慰自己哼御,他們只是感情好坯临,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著恋昼,像睡著了一般看靠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上焰雕,一...
    開(kāi)封第一講書(shū)人閱讀 49,007評(píng)論 1 284
  • 那天衷笋,我揣著相機(jī)與錄音,去河邊找鬼矩屁。 笑死辟宗,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的吝秕。 我是一名探鬼主播泊脐,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼烁峭!你這毒婦竟也來(lái)了容客?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤约郁,失蹤者是張志新(化名)和其女友劉穎缩挑,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體鬓梅,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡供置,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了绽快。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片芥丧。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖坊罢,靈堂內(nèi)的尸體忽然破棺而出续担,到底是詐尸還是另有隱情,我是刑警寧澤活孩,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布物遇,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏挎挖。R本人自食惡果不足惜这敬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蕉朵。 院中可真熱鬧崔涂,春花似錦、人聲如沸始衅。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)汛闸。三九已至蝙茶,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間诸老,已是汗流浹背隆夯。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留别伏,地道東北人蹄衷。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像厘肮,于是被迫代替她去往敵國(guó)和親愧口。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345