Prop
是數據由父組件向子組件流動的 單向數據流,也就代表子組件無法透過 Prop
更改父組件的數據(注意,盡量不要 prop 物件,由於 call by reference
,子組件更動物件 prop 會影響到父組件),這時候若是想要將子組件的數據傳遞給父組件,可以透過子組件 自定義事件
並將想傳遞給父組件的數據透過 $emit
第二個參數定義。父組件對於該 自定義事件
監聽,一旦 自定義事件
發生,數據便可以自子組件中拋出給父組件。
簡單來說,一旦涉及父、子組件的數據傳遞,可以透過簡單的口訣 Props down, Event up 記憶:
父組件
透過 Prop
將數據傳遞給 子組件
。(下箭頭)子組件
設定 自定義事件
同時定義事件發生時將傳遞給父組件的數據,父組件透過監聽該 自定義事件
得到子組件傳出的數據。(上箭頭)自定義事件
在此建立一個簡單的子組件 自定義事件
,透過 instance method $emit('event-name', [...arguments])
觸發當前 instance 組件事件。
使用 $emit
非常簡單,只需要定義自定義事件名稱,並且透過第二個參數定義隨事件拋出的子組件數據,該參數會傳給事件監聽器的 callback
。
補充:
和 prop 不同,自定義事件名稱不會作為 javascript 變數或 property,所以不需要使用 camelCase,Vue 推薦使用 kebab-case 事件名稱。
o → my-event ; x → myEvent
一旦點擊子組件按鈕,將透過 $emit
發送 自定義事件
component-event
,並且我們也定義了要隨事件拋出的數據 number
Vue.component("my-component", {
data() {
return {
number: 12
}
},
template: `
<div class="child">
<span>? 這是一個子組件</span>
<button @click="$emit('component-event', number)">父組件 count 加 {{ number }}</button>
</div>`
});
同一時間,父組件需要監聽該自定義事件,並且透過 $event
訪問被拋出的數據 number
。
這樣透過監聽自定義事件的方法,子組件的數據便可以傳遞給父組件。在需要子組件數據時,便可以使用此方法。
const vm = new Vue({
el: ".app",
data: {
count: 0
},
template: `
<div class="app">
<p>父組件總計數:{{ count }}</p>
<my-component @component-event="count+=$event" />
</div>`
});
有時候,會需要將多筆數據自子組件中拋出,這個時候使用 $event 會只拿到第二個被拋出的參數。
Vue.component("my-component", {
data() {
return {
number: 12,
text: "hello",
author: "RURU"
};
},
template: `
<div class="child">
<span>? 這是一個子組件</span>
<button @click="$emit('component-event', text, author, number)">拋出值 number: 12, text: 'hello', author: 'RURU' 給父組件</button>
</div>`
});
const vm = new Vue({
el: ".app",
data: {
count: 0,
data: null
},
template: `
<div class="app">
<p>父組件接收到的子組件值:{{ data }}</p>
<my-component @component-event="print($event)" />
</div>`,
methods: {
print(number, text, author) {
console.log(number, text, author);
this.data = { number, text, author };
}
}
});
我們可以看到傳出的三個參數 number
、text
、author
,透過 $event
我們只能拿到第一個。
這時候可以透過 arguments
取得所有拋出的數據。^來源^
Vue.component("my-component", {
data() {
return {
number: 12,
text: "hello",
author: "RURU"
};
},
template: `
<div class="child">
<span>這是一個子組件</span>
<button @click="$emit('component-event', text, author, number)">拋出值 number: 12, text: 'hello', author: 'RURU' 給父組件</button>
</div>`
});
const vm = new Vue({
el: ".app",
data: {
count: 0,
data: null
},
template: `
<div class="app">
<p>父組件接收到的子組件值:{{ data }}</p>
<my-component @component-event="print(...arguments)" />
</div>`,
methods: {
print(number, text, author) {
console.log(number, text, author);
this.data = { number, text, author };
}
}
});
使用 arguments
後,可以取得所有的拋出數據。
組件上的事件有分成兩個系統,一個是 自定義事件
,一個是 原生事件
,若要在組件上監聽 原生事件
,可以透過 v-on
添加 .native
修飾符,監聽子組件上的原生事件。
透過 native
,可以對根元素監聽 click
事件。
Vue.component("my-component", {
template: `
<div class="child">
<span>這是一個子組件</span>
<button>父組件 count 加一</button>
</div>`
});
const vm = new Vue({
el: ".app",
data: {
count: 0
},
template: `
<div class="app">
<p>父組件總計數:{{ count }}</p>
<my-component @click.native="count++" />
</div>`
});
以上為此次內容,感謝看到這裡的你,明天會說明在組件中使用 v-model
。
若是文中有任何錯誤、錯字、想討論的內容,歡迎各位大大不吝鞭笞指正、交流分享,筆者不慎感激 ✦ ✦ ✦
▶︎ 筆者 github:https://github.com/YUN-RU-TSENG
▶︎ 老王賣瓜之筆者另一篇鐵人:每天來點 CSS Specification
▶︎ 倘若不斷向深處扎根,似乎就能茁壯成長 - RM