上一章介紹了父層傳子層的 props,這章就來介紹一下子層傳父層的 $emit
我們直接用範例來解說好了~
這個範例要實現的功能是一個計數器,架構的部分會建立一個 component 裡面是一個 button,點擊時 count 會 +1 並傳到父層顯示。
首先第一件事就是先建立一個 component -> button-count
裡面有一個 button,然後我們在 component 裡面寫一個 increment 的 methods,在 button 上綁定 increment 的 click 事件,這將我們就能夠點擊的時候 count +1,到這邊應該都還很簡單,前面幾章都做過了。
但是這時候的 count 資料還是在 component 裡面,我們接下來要做的就是利用 $emit
將資料傳送至父層,首先我們要的是在點擊的時候同步將資料傳送至父層,所以我們就在 increment 裡面寫上一個 $emit 方法:
this.$emit('increment', this.count);
//第一個參數會是你要綁定的事件名稱
//第二個是你要透過這事件傳至父層的資料
接下來我們要在 component tag 上綁定剛剛在 component 內寫的 $emit 事件名稱,然後在父層寫一個 methods 讓 $emit 事件觸發的時候執行:
<button-count @increment="incrementTotal"></to-do-list>
//@increment 是 $emit 綁定的事件名稱
//incrementTotal 是父層的 methods
這邊要特別注意一點,$emit 事件的命名不能為大寫,所以能夠採用 kebab-case
命名。
如果使用大寫命名它會自動把它解析為小寫,這樣可能會出現命名不同的情況
<body>
<div id="app">
count: {{count}}<br>
<button-count @increment="incrementTotal"></to-do-list>
}
</div>
</body>
<script>
const vm = new Vue({
el: '#app',
data: {
count: ''
},
methods: {
incrementTotal(count) {
this.count = count;
//觸發事件執行時會接收 component 傳來的資料,將它賦值給 data 並渲染
}
},
components: {
'button-count': {
data() {
return {
count: 0
}
},
template: `<button @click="increment">+1</button>`,
methods: {
increment() {
this.count += 1;
this.$emit('increment', this.count);
}
}
}
}
})
</script>
結果就會是這樣囉~
$emit 大致上的流程就是這樣,接下來我們就將上一章的 To Do List 做完整吧,接下來要做的就是點擊 component 裡面的 remove button 能夠將該項目移除掉,那該怎麼做呢?!
先來看一下先前 remove 的 methods 怎麼寫
removeToDo(index) {
this.todos.splice(index, 1)
}
但是我們現在 v-for 是在 component 裡面執行的,所以現在 index 是在 component 裡面,我們必須將他傳至父層,並把該項目移除。
下面我們就動手將 remove 的事件完成吧~
<body>
<div id="app">
<input type="text" v-model="newTodo">
<button @click="addToDo">Add</button>
<to-do-list :todos="todos" @removeIndex="removeToDo"></to-do-list>
</div>
</body>
<script>
const vm = new Vue({
el: '#app',
data: {
newTodo: '',
todos: []
},
methods: {
addToDo() {
this.todos.push(this.newTodo);
this.newTodo = '';
},
removeToDo(index) {
this.todos.splice(index, 1);
//接到 index 後移除項目
}
},
components: {
'to-do-list': {
props: ['todos'],
template: `<ul>
<li v-for="(todo, index) in todos">{{todo}}
<button @click="getRemoveIndex(index)">Remove</button>
</li>
</ul>`,
methods: {
getRemoveIndex(index) {
this.$emit('removeIndex', index)
//將 index 透過 $emit 事件傳送
}
}
}
}
})
</script>
這樣就都了解如何在子父層間傳值了呢~
接下來下一章會開始介紹在 Vue 裡面也很重要的生命週期囉~