第12屆鐵人賽Day 11 Vue元件單向傳遞: $emit 製作todo list
經過昨天介紹$emit
可以傳遞自訂的事件給父層元件之後,今天來利用$emit
的特性,設計一個有的to-do list吧!3M
便利貼風格
實作需求:
-
新增
我想要在input
欄位裡,讓使用者從Todos
元件輸入本日代辦事項, 按完enter
送出後,把資料送去Root
元件裡顯示。 -
刪除
點擊任一的todo item
,就可以把item從todo
陣列裡移除。
Step0. Todos元件:設計template
把input form
綁上雙向事件處理的v-on
,讓使用者enter
送出後呼叫createItem
這個methods裡面的function。
Step1. Todos元件的methods: $emit('自訂事件名稱')
傳出事件
createItem($event)
方法裡面帶了參數,讓我們可以把$event.target.value
傳到上層的Vue Instance。
Todos.vue
<template id="todo-3M">
<div class="todo-form">
<label>本日To do list</label><i class="fas fa-pencil-alt" ></i><hr>
<input class="todo-input" type='text' @keyup.enter="createItem" placeholder="請輸入您今天的代辦事項">
</div>
</template>
<script>
export default {
methods: {
createItem($event){
this.$emit("additem", $event.target.value)
$event.target.value = ""
}
},
template: "#todo-3M"
}
</script>
<style scoped>
<!-- 略 -->
</style>
Step2. 在Vue Root掛載點,接收傳出來的事件
Vue Root掛載點內的<Todos>
元件,綁上雙向事件處理的v-on
,
讓<Todos>
元件傳遞出來的additem
可以跟Root元件的addMoreItem
綁定
home.html.erb
<div id="content">
<div class="main-title">Vue.js x Rails第12屆鐵人賽專案:</div>
<div class="main-body">本日主題:</div>
<Todos @additem="addMoreItem"></Todos>
<ul class="todo-item">
<li v-for="todo in todos" @click="removeItem(todo)"><i class="far fa-calendar-check"></i> </li>
</ul>
<Foot></Foot>
</div>
Step3. 父元件接收事件後,執行addMoreItem()
function
我的todos
陣列初始值預設有三件代辦事項。父元件接收事件之後,還可以再把其他代辦事項push
進去這個陣列。
Step4. v-for
裡的todo迴圈,使用@click
事件綁定removeItem(todo)
function
若對單一todo
item點擊,則透過javascript的splice
方法,把該項todo item從陣列中移除。
home.js
import TurbolinksAdapter from 'vue-turbolinks'
import Vue from 'vue/dist/vue.esm'
import Todos from "../components/todos"
import Foot from "../components/foot"
Vue.use(TurbolinksAdapter)
document.addEventListener('turbolinks:load', () => {
let el = document.querySelector("#content");
if (el){
new Vue({
el,
data: {
day: "第 11 天",
topic: "元件的由內而外傳遞事件 - emit",
todos: ["買咖啡", "買口罩", "去郵局"],
},
methods: {
addMoreItem(item){
this.todos.push(item)
},
removeItem(item){
let itemIndex = this.todos.indexOf(item)
if (itemIndex >= 0){
// 從array中刪除項目,並回傳被刪除後的項目
this.todos.splice(itemIndex, 1)
}
}
},
components: { Todos, Foot }
})
}
})
完成圖:
如果非父子元件之間傳遞,而是平行階層、或是跨階層的元件資料傳遞, 我們會透過Vue的event bus來實作,或者是以Vuex進行狀態管理。 這就是明後兩天要介紹的部份囉~請待下回分解!
Ref: