1. 概述
相關(guān)定律告訴我們:這個世界上的任何事物之間都會存在一定聯(lián)系,“城門失火涵亏,殃及池魚”就是一個很好的例子宰睡。因此如果我們能夠盡早發(fā)現(xiàn)這些看不見的聯(lián)系,就能很好的解決更多遇見的難題气筋。
言歸正傳拆内,之前我們聊過如何在子組件中去修改主組件傳遞的參數(shù)的值,當時是在子組件中重新聲明一個新數(shù)據(jù)宠默,初始值為父組件傳參的值麸恍,然后對子組件的數(shù)據(jù)進行計算。
今天我們使用事件的方式來實現(xiàn)對父組件的傳參進行修改搀矫。
2. 組件間事件通信
2.1 子組件接收參數(shù)并實現(xiàn)自增
<body>
<div id="myDiv"></div>
</body>
<script>
const app = Vue.createApp({
data() {
return {
num : 1
}
},
template:`
<div>
<test :num="num" />
</div>
`
});
app.component("test", {
props:['num'],
methods : {
incrNum() {
this.num++;
}
},
template:`
<div @click="incrNum" >{{num}}</div>
`
});
const vm = app.mount("#myDiv");
這個例子咱們之前聊過抹沪,父組件有一個數(shù)據(jù) num,父組件將這個參數(shù)傳給 test 子組件瓤球,子組件使用 props:['num'] 的方式接收后融欧,在事件方法中對其自增
很明顯,自增時會報錯冰垄,因為父組件傳過來的 num 是只讀的蹬癌,子組件不能對其進行修改权她。
2.2 子組件中聲明新的數(shù)據(jù)虹茶,將父組件的num作為初始值
const app = Vue.createApp({
data() {
return {
num : 1
}
},
template:`
<div>
<test :num="num" />
</div>
`
});
app.component("test", {
props:['num'],
data() {
return {
myNum : this.num
}
},
methods : {
incrNum() {
// this.num++;
this.myNum++;
}
},
template:`
<div @click="incrNum" >{{myNum}}</div>
`
});
這是我們上節(jié)課的解決方案,在子組件中聲明 myNum隅要,把num當做初始值蝴罪,然后自增 myNum,顯示時也顯示 myNum
很明顯步清,這樣做是可以的
2.3 子組件調(diào)用父組件的方法
既然子組件無權(quán)修改父組件傳過來的參數(shù)要门,那我們就讓父組件自己去修改這個參數(shù)
const app = Vue.createApp({
data() {
return {
num : 1
}
},
methods : {
handleIncr() {
this.num++;
}
},
template:`
<div>
<test :num="num" @incrNum="handleIncr" />
</div>
`
});
app.component("test", {
props:['num'],
methods : {
incrNum() {
this.$emit('incrNum')
}
},
template:`
<div @click="incrNum" >{{num}}</div>
`
});
這個例子中虏肾,父組件在使用子組件時,綁定了一個事件 incrNum欢搜,這個事件會調(diào)用父組件的 handleIncr 方法封豪,這個方法中對數(shù)據(jù) num 進行了自增。
子組件在自己的 incrNum 方法中使用 this.$emit('incrNum') 觸發(fā)了父組件的 incrNum 事件炒瘟,然后該事件調(diào)用父組件的 handleIncr 方法吹埠,對父組件的數(shù)據(jù) num 進行修改。
父組件修改了數(shù)據(jù) num疮装,這個數(shù)據(jù) num 修改后的值會傳遞給子組件缘琅,從而實現(xiàn)對 num 參數(shù)的修改。
說了這么一大堆廓推,簡單看就是子組件通過某種手段調(diào)用了父組件的方法刷袍。
經(jīng)試驗,完全沒用問題樊展,可以修改 num 的值
2.4 子組件調(diào)用父組件的方法呻纹,且傳參
光調(diào)用還不行,我們還要傳參
const app = Vue.createApp({
data() {
return {
num : 1
}
},
methods : {
handleIncr(param1) {
this.num += param1;
}
},
template:`
<div>
<test :num="num" @incrNum="handleIncr" />
</div>
`
});
app.component("test", {
props:['num'],
methods : {
incrNum() {
this.$emit('incrNum', 2)
}
},
template:`
<div @click="incrNum" >{{num}}</div>
`
});
這個例子中专缠,我們根據(jù)傳參的值居暖,決定自增多少。
在 this.$emit('incrNum', 2) 這句代碼中藤肢,除了指明觸發(fā)的事件太闺,還傳了一個參數(shù),父組件的 handleIncr(param1) 這個方法嘁圈,就可以接收這個參數(shù)省骂,并使用
2.5 子組件調(diào)用父組件的方法,且傳多個參數(shù)
這次我們要傳多個參數(shù)最住,當然也是可以的
const app = Vue.createApp({
data() {
return {
num : 1
}
},
methods : {
handleIncr(param1, param2) {
this.num += param2;
}
},
template:`
<div>
<test :num="num" @incrNum="handleIncr" />
</div>
`
});
app.component("test", {
props:['num'],
methods : {
incrNum() {
this.$emit('incrNum', 2, 3)
}
},
template:`
<div @click="incrNum" >{{num}}</div>
`
});
這么傳:this.$emit('incrNum', 2, 3)钞澳,這么收:handleIncr(param1, param2),以此類推
2.6 計算邏輯放在子組件中
自增本來是子組件的業(yè)務涨缚,我們不想把這個邏輯放到父組件中轧粟,耦合性太強了,我們可以這么寫
const app = Vue.createApp({
data() {
return {
num : 1
}
},
methods : {
handleIncr(param1) {
this.num = param1;
}
},
template:`
<div>
<test :num="num" @incrNum="handleIncr" />
</div>
`
});
app.component("test", {
props:['num'],
methods : {
incrNum() {
this.$emit('incrNum', this.num + 1)
}
},
template:`
<div @click="incrNum" >{{num}}</div>
`
});
其實就是傳參時在子組件中計算好了脓魏,然后父組件直接賦值就好
2.7 通過 v-model 的方式兰吟,修改父組件數(shù)據(jù)的值
上面的例子中,我們通過子組件調(diào)用父組件的方法去修改父組件數(shù)據(jù)的值茂翔,耦合性還是有點強混蔼,父組件需要去為子組件寫一個方法。
其實還有一個更簡潔的辦法珊燎,就是通過 v-model 的方式惭嚣,來看下面的例子
const app = Vue.createApp({
data() {
return {
num : 1
}
},
template:`
<div>
<test v-model="num" />
</div>
`
});
app.component("test", {
props:['modelValue'],
methods : {
incrNum() {
this.$emit('update:modelValue', this.modelValue + 1);
}
},
template:`
<div @click="incrNum" >{{modelValue}}</div>
`
});
這個例子中遵湖,父組件使用 test 子組件時,使用 v-model="num" 的方式來傳參晚吞。
test 子組件接收時延旧,使用 props:['modelValue'] 的方式接收,注意:modelValue 是一個固定寫法槽地。
在子組件的自增方法中使用 this.$emit('update:modelValue', this.modelValue + 1); 的形式去修改 modelValue 的值垄潮,注意:update:modelValue 是固定寫法。
2.8 使用 num 替換 modelValue
上面的例子有點不好理解闷盔,無緣無故蹦出個 modelValue弯洗,父組件明明傳的是 num,為啥我接受要用 modelValue逢勾,太奇怪了
下面的例子更易于我們的理解
const app = Vue.createApp({
data() {
return {
num : 1
}
},
template:`
<div>
<test v-model:num="num" />
</div>
`
});
app.component("test", {
props:['num'],
methods : {
incrNum() {
this.$emit('update:num', this.num + 1);
}
},
template:`
<div @click="incrNum" >{{num}}</div>
`
});
這個例子就好理解多了牡整,首先父組件使用 test 子組件時慷蠕,使用 v-model:num="num" 進行傳參浅役。
子組件接收時旁蔼,接收的就是 num覆获,使用 props:['num'] 接收。
最后使用 this.$emit('update:num', this.num + 1); 代碼對接收到的 num 進行修改欧芽。
顯示時顯示的也是 num症脂,{{num}}
這樣寫就清爽很多织鲸,父組件沒有 method句占,子組件相當于自己對接收到的參數(shù) num 進行操作沪摄,耦合度降低了很多。
3. 綜述
今天聊了一下 VUE3 的 組件間事件通信纱烘,希望可以對大家的工作有所幫助杨拐,下一節(jié)我們繼續(xù)講組件的相關(guān)知識,敬請期待
歡迎幫忙點贊擂啥、評論哄陶、轉(zhuǎn)發(fā)、加關(guān)注 :)
關(guān)注追風人聊Java哺壶,每天更新Java干貨屋吨。