前端技術紀錄、everything I know

0%

【Vue】$emit,透過客製化事件把子元件的資料傳到母元件

外部資料傳遞進元件裡

如果我們想要從子元件傳遞資料到母元件,我們必須使用$emit 建立一個客製化的事件,再透過這個事件,把資料投擲進到母元件。要怎麼做呢?概念其實和 props 差不多。當我們要把根元件的資料傳進子元件,需要透過 props 的方法,在子元件中建立一個接收資料的環境。

同樣的,子元件要投遞資料到母元件,也會需要先在子元件打造一組工具(客製化事件、custom event),讓 Vue 先建構一個客製化事件。最後,再透過 DOM 模板,綁定這個工具,進一步呼叫母元件的函式。


分隔線

元件觸發事件的過程

先來複習一下根元件綁定事件的過程:

1
2
<button @click="incrementTotal"></button>
<button-compo></button-compo>

^

1
2
3
4
5
6
7
8
9
10
11
var app = new Vue({
el: '#app',
data: {
cash: 300
},
methods: {
incrementTotal: function () {
this.cash++;
}
}
});

^

子元件呼叫根元件的 method

如果,我們今天要將 incrementTotal 綁定到元件上,是不可行的。像這樣:

<component @click="incrementTotal"></component> (錯誤示範)

這是因為,我們無法在子元件直接使用母元件的任何東西,data、methods 都是。如果想要使用母元件的事件,我們就需要在子元件建立一個客製化事件(custom event),再透過這個事件的指令呼叫母元件的 method。

子元件中

x-template

1
<button @click="incrementCounter" class="btn btn-outline-primary">增加 {{ counter }} 元</button>

子元件的 template 事件呼叫建立客製化事件的函式
^

1
2
3
4
5
6
7
8
Vue.component('component',{
//...略
methods: {
incrementCounter: function () {
this.$emit('increment'); //建立一個客製化事件
}
}
})

可以看到,在這邊子元件中 x-template 綁定的事件 incrementCounter 呼叫的函式,做的事情只有 this.$emit('emit-event-name')。這個 $emit 就是 Vue 提供我們建立客製化事件的方法。

所以,emit 雖然聽起來有些複雜,但我們需要做的,就只有:

  1. 子元件中綁定一個建立客製化事件的事件,
  2. 透過事件的綁定方式,把這個新的客製化事件,綁定到子元件的 DOM 模板中
1
<component @custom-event="rootMethod"></component>

這樣就達成子元件呼叫根元件的目的了。

那資料呢?

說了這麼多,還沒講到資料。資料的部分,也是透過 this.$emit() 這個方法傳遞的。在這個方法中,第一個參數為這個客製化事件的名稱,第二的參數就是要投擲到母元件的資料啦!如下:

子元件

1
this.$emit('name', this.dataName)

不過,這樣還沒結束。在跨元件的傳遞中,如果設定了一方,另一方一定也會有相對應的設定。這樣 Vue 才會知道,要在哪「兩個」元件之間做傳遞。所以,在這個範例中,子元件已經做好傳遞資料的準備,根元件當然也要有個地方接收子元件的資料。因為上述都是和事件相關的設定,想當然母元件接收資料的地方,也會是在 methods 裏頭:

母元件

1
2
3
4
5
methods:{
rootMethod(num){
this.dataName += num;
}
}


記得嗎?上述我們透過客製化事件呼叫根元件的函式 <component @custom-evnet="rootMethod"></component>,如果要接收資料,透過在這個函式建立一個參數,Vue 就會知道這個參數等於子元件傳出來的資料了。

如此一來,我們就能透過母元件做子元件資料的計算。