文章較長可按目錄跳轉瀏覽
- 前言
- 準備作業
- 1.父組件
- 2.子組件
- 3.孫組件
- 組件間傳值
- 1.父傳子
- 2.子傳父
- 3.爺傳孫
- 4.孫傳爺
- 拓展
- 1.自定義屬性
- 2.自定義事件
- 3.$attrs
- 4.$listeners
- 5. inheritAttrs
- 結語
前言
看了很多vue組件間傳參的帖子,發現很多不完整,今天閑來無事總結一下vue組件間傳值,此文涉及到:父傳子,子傳父,爺傳孫,孫傳爺的組件間傳值,寫的比較詳細,同學們也別嫌我啰嗦,此文應該達到了保姆級別,看不明白你來打我,
本次用到的三個組件分別命名為:Father,Son,GrandSon,
準備作業
首先看下三個組件的代碼:
1.父組件
<template>
<div class="father">
<h1>父組件</h1>
<Son></Son>
</div>
</template>
2.子組件
<template>
<div class="son">
<h1>子組件</h1>
<GrandSon></GrandSon>
</div>
</template>
3.孫組件
<template>
<div class="grandson">
<h1>孫組件</h1>
</div>
</template>
為方便區分這里簡單寫了一下樣式,渲染效果如圖:

組件間傳值
1.父傳子
首先將父組件的中toSon的值在父組件內渲染,
<template>
<div class="father">
<h1>父組件</h1>
<h1>{{toSon}}</h1>
<Son></Son>
</div>
</template>
<script>
import Son from './Son.vue'
export default {
name: "Father",
components:{ Son },
data(){
return{
toSon:"這是父組件傳給子組件的值!~"
}
}
}
</script>
注意:這里還沒有進行傳參

眾所周知:父傳子是使用自定義屬性傳參,使用props接收資料,
我們在父組件中使用的子組件處定義自定義屬性:son,
<Son :son="toSon"></Son>
然后我們在子組件中接收資料,接收使用的son一定和前面的自定義屬性:son對應,
props: {
son:String
},
也可以這樣寫:
props:["son"],
第一種寫法可以指定接收的資料型別或者默認值,第二種寫法比較便捷,可以按陣列的形式直接加逗號往后排,
然后我們在子組件中使用接收的資料,
<template>
<div class="son">
<h1>子組件</h1>
<h1>{{son}}</h1>
<GrandSon></GrandSon>
</div>
</template>
然后父傳子就完成了,如圖所示:

2.子傳父
首先將需要傳給父組件的子組件的值在子組件內部渲染出來:
<template>
<div class="son">
<h1>子組件</h1>
<h1>{{toFather}}</h1>
<GrandSon></GrandSon>
</div>
</template>
<script>
import GrandSon from './GrandSon.vue'
export default {
name: "Son",
components:{ GrandSon },
data(){
return{
toFather:"這是子組件傳給父組件的值!~"
}
}
}
</script>
注意:這里還沒有傳參

子傳父靠的是自定義事件,接收資料使用的是$emit,
這里我們在h1上加一個點擊事件,呼叫sendToFather的方法,后期用來觸發我們的自定義事件,
<template>
<div class="son">
<h1>子組件</h1>
<h1 @click="sendToFather">{{toFather}}</h1>
<GrandSon></GrandSon>
</div>
</template>
然后在methods里處理此方法:
methods:{
sendToFather() {
this.$emit("father",this.toFather)
}
}
father表示我們觸發點擊事件呼叫函式sendToFather后,會觸發自定義事件father,this.toFather表示子組件中要傳給父組件的值,
在子組件處理完畢后我們進入父組件,需要在父組件呼叫子組件的位置添加自定義事件father,然后函式getFromSon就可以接收傳來的資料,為了更直觀化,我們先放一個坑valueOfSon用來接收資料,父組件代碼如下:
<template>
<div class="father">
<h1>父組件</h1>
<h1>{{valueOfSon}}</h1>
<Son @father="getFromSon"></Son>
</div>
</template>
<script>
import Son from './Son.vue'
export default {
name: "Father",
components:{ Son },
data(){
return{
valueOfSon:"子組件接收資料的坑~"
}
},
methods:{
getFromSon(val){
this.valueOfSon=val
}
}
}
</script>
未傳值時,頁面如圖:

然后我們點擊子組件中h1:這是子組件傳給父組件的值!~,觸發sendToFather函式,然后觸發自定義事件father,將toFather的值傳走,父組件中的father事件觸發,呼叫getFromSon函式,將接收的值傳給valueOfSon,我們就會發現留的坑資料改變為這是子組件傳給父組件的值!~,傳值成功,

3.爺傳孫
首先說明:既然你學會了父傳子,那么爺傳孫自然不是難事,你可以先父傳子,再子傳孫,一步一步傳,這里不再贅述,
這里用到的方法是$attrs傳參,比起上面的更簡潔一些,首先我們還是來一個初始狀態,先將父組件的引數在父組件自身展示一下:
<template>
<div class="father">
<h1>父組件</h1>
<h1>{{toGrandSon}}</h1>
<Son></Son>
</div>
</template>
<script>
import Son from './Son.vue'
export default {
name: "Father",
components:{ Son },
data(){
return{
toGrandSon:"父組件傳給孫組件的值!~"
}
},
}
</script>
注意:現在還未傳參

首先我們需要先在父組件參考的子組件上使用自定義屬性,將值先傳給子組件,這里我們定義自定義屬性:grandson,
<template>
<div class="father">
<h1>父組件</h1>
<h1>{{toGrandSon}}</h1>
<Son :grandson="toGrandSon"></Son>
</div>
</template>
然后重點來了:我們此時不需要使用props在子組件接收資料,而是直接在子組件參考的孫組件上面系結v-bind="$attrs",在這里此段代碼就像導管一樣,直接將資料傳給了孫組件,
<template>
<div class="son">
<h1>子組件</h1>
<GrandSon v-bind="$attrs"></GrandSon>
</div>
</template>
那么如果說它將資料導給了孫組件,那么我們此時就可以在孫組件內部使用props接收資料,然后我們將接收到的資料展示出來,
<template>
<div class="grandson">
<h1>孫組件</h1>
<h1>{{ grandson }}</h1>s
</div>
</template>
<script>
export default {
name: "GrandSon",
props:{
grandson:String
}
}
</script>
接收成功,效果如圖:

4.孫傳爺
與上同理:既然你學會了子傳父,那么孫傳爺也不是難事,你可以先子傳父,再父傳爺,一步一步傳,這里不再贅述,
這里用到的方法是$listeners傳參,比起上面的更簡潔一些,首先我們還是來一個初始狀態,先將孫組件的引數在孫組件自身展示一下:
<template>
<div class="grandson">
<h1>孫組件</h1>
<h1>{{ toFather }}</h1>
</div>
</template>
<script>
export default {
name: "GrandSon",
data(){
return{
toFather:"孫組件傳給父組件的值!~"
}
}
}
</script>

這里給h1:"孫組件傳給父組件的值!~"添加一個點擊事件來觸發sendToFather函式來傳參:
<template>
<div class="grandson">
<h1>孫組件</h1>
<h1 @click="sendToFather">{{ toFather }}</h1>
</div>
</template>
然后在methods中處理sendToFather函式:
methods:{
sendToFather(){
this.$emit("father",this.toFather)
}
}
這里觸發的是自定義事件father,后面定義,傳走的值是toFather:"孫組件傳給父組件的值!~"
然后重點來了:我們此時不需要使用自定義事件"father"在子組件接收資料,而是直接在子組件參考的孫組件上面系結v-on="$listeners",在這里此段代碼就像導管一樣,直接將資料傳給了父組件,
<template>
<div class="son">
<h1>子組件</h1>
<GrandSon v-on="$listeners"></GrandSon>
</div>
</template>
子組件部分處理完畢,再來看父組件,這里先來個坑用來接收資料,然后定義之前提到的自定義事件father,使其呼叫getFromGrandSon函式,然后在函式getFromGrandSon中處理資料,父組件代碼如下:
<template>
<div class="father">
<h1>父組件</h1>
<h1>{{ valueOfGrandSon }}</h1>
<Son @father="getFromGrandSon"></Son>
</div>
</template>
<script>
import Son from './Son.vue'
export default {
name: "Father",
components:{ Son },
data(){
return{
valueOfGrandSon:"接收孫組件傳參的坑~"
}
},
methods:{
getFromGrandSon(val){
this.valueOfGrandSon=val
}
}
}
</script>
未傳參時,如圖所示:

此時點擊子組件中的h1文字觸發點擊事件,執行sendToFather函式,然后觸發自定義事件father,在子組件中$listeners起到導管作用,將事件傳給父組件,然后父組件中的father事件被觸發,執行getFromGrandSon函式,將傳來的值賦給valueOfGrandSon,
如圖所示:

OK!~,大功告成,到這里父傳子,子傳父,爺傳孫,孫傳爺就結束了,下面進行一些小拓展,已經理解的同學可以跳過,
拓展
只是自己的一點見解,如有錯誤歡迎指正,
1.自定義屬性
- 在vue中我們經常用到一些動態屬性,如
:class,:id,:src,:key等等,
這些屬性有一個共同的特性那就是:他們都是系統規定好的,有特定作用的,比如:class后面跟值,可以動態系結該元素的class,
此類屬性,我統稱為:系統自帶的屬性, - 而有一些屬性是我們自己來寫的,如上文中的
:son和:grandson,這些屬性只有我們自己知道他們是用來干嘛的,你甚至可以寫:abc,:qwerdf來自定義這些屬性,
此類屬性,我統稱為:自定義屬性, 需要強調的是,使用父傳子或者爺傳孫的時候,一定要使用自定義屬性,如果你使用了系統自帶的屬性來傳參是萬萬行不通的,
2.自定義事件
- 在vue中我們也經常用到一些事件,如
@click,@dbclick,@keyup,@keydowm等等,
這些事件有一個共同的特性那就是:他們都是系統規定好的,有特定作用的,比如@click,就規定你點擊某個區域來觸發后面執行的函式,
此類事件,我統稱為:系統自帶的事件, - 而有一些事件是我們自己來寫的,如上文中的
@father,這些事件只有我們自己知道他什么時候被觸發,上文中觸發機制都寫在了點擊事件里,你也可以有更多的選擇,你甚至可以寫@abc,@qwerdf來自定義這些事件,
此類事件,我統稱為:自定義事件, 需要強調的是,使用子傳父或者孫傳爺的時候,一定要使用自定義事件,如果你使用了系統自帶的事件來傳參也是萬萬行不通的,
3.$attrs
$attrs是在vue的2.40版本新增的,- 包含了父作用域中不作為
prop被識別 (且獲取) 的特性系結 (class和style除外),當一個組件沒有宣告任何prop時,這里會包含所有父作用域的系結 (class和style除外),并且可以通過v-bind="$attrs"傳入內部組件——在創建高級別的組件時非常有用, - 簡單講就是包含了所以父組件在子組件上設定的屬性(除了
prop傳遞的屬性、class和style),
4.$listeners
$listeners是在vue的2.40版本新增的,- 包含了父作用域中的 (不含
.native修飾器的)v-on事件監聽器,它可以通過v-on="$listeners"傳入內部組件——在創建更高層次的組件時非常有用, - 簡單點講它是一個物件,里面包含了作用在這個組件上所有的監聽器(監聽事件),可以通過
v-on="$listeners"將事件監聽指向這個組件內的子元素(包括內部的子組件),
5. inheritAttrs
$listeners是在vue的2.40版本新增的,- 型別:
boolean - 默認值:
true - 如果父組件給子組件傳遞資料,子組件不使用
props接收,那么這些資料將作為子組件的HTML元素的特性,這些特性系結在組件的HTML根元素上, - 如果不希望本組件的根元素繼承父組件的
attribute,同時父組件傳過來的屬性(沒有被子組件的props接收的屬性),也不希望顯示在子組件的dom元素上可以使用inheritAttrs: false,但是在子組件里可以通過$attrs獲取到沒有使用的注冊屬性,inheritAttrs: false不會影響 style 和class的系結,
如:我在父組件中系結自定義屬性:abc,接收資料msg:"666"
<Son :abc="msg"></Son>
data(){
return{
msg:"666"
}
}
在子組件中不適用props接收,我們就會看到這樣的情況:自定義屬性被渲染在了子組件的div上,
<div class="son" abc="666">
<h1>子組件</h1>
</div>
而如果我們添加了inheritAttrs: false,如下:
export default {
name: "Son",
inheritAttrs: false,
components:{ GrandSon },
}
則會渲染成以下,自定義的屬性消失了,
<div class="son">
<h1>子組件</h1>
</div>
注意:對inheritAttrs操作不影響我們對$attrs的使用,
結語
文章到這里就結束了,如果你在這里學到了一些東西,希望能給我一個點贊,評論和收藏,十分感謝你的支持,博客之路我會本著認真的態度一直寫下去,加油 ?(・ω・)ノ
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/328014.html
標籤:其他
下一篇:Vue指令大全(不定時更新)
