# 25. TodoList 頁面模組 1 - 新增
在這個範例中,畫面可分為三個模組:
- 「新增資料」模組
- 「列表顯示」模組
- 「修改事項」模組
這個小節主要說明「新增資料」的模組,也就是 input
輸入框。
# 畫面初始化
在建立模組之前,我們可以先在專案進入口 "App.vue" 進行初始化:
- 在
mounted
階段載入資料。 - 透過
computed
拿到資料的索引值。
//- App.vue
<script>
export default {
computed: {
todoIndex() {
return this.$store.getters["todoIndex"];
}
},
mounted() {
this.$store.dispatch("INIT_TODOS");
},
}
</script>
# 輸入框的處理細節
要實現新增功能,需要先有輸入框讓使用者輸入內容。而處理輸入框的內容時,須注意這幾個細節:
- 去除首尾空白
- 判斷是否為空值
- 清空輸入框
# 建立「新增資料」模組
在 "components" 資料夾建立 "TodoInput" 資料夾,並在裡面新增以下檔案:
- index.vue
- template.html
- style.css (視需求,如果 CSS 樣式另外管理,則無需在此建立樣式檔案)
# template.html
- 主要內容為
input
輸入框,但建議在最外層加上一個div
,確保最外層只有一個元素。 input
輸入框有幾個要點:- 使用
v-model
雙向綁定資料todo
,並用trim
去除空白。 - 鍵盤按下 "Enter" 後,即可觸發事件以新增事項。
- 使用
//- components/TodoInput/template.html
<div class="todoInput">
<input
type="text"
placeholder="請輸入待辦事項"
v-model.trim="todo"
@keyup.enter="submitHandler"
/>
</div>
# index.vue
- 在
data
中建立todo
暫存輸入框的內容 (雙向綁定)。 - 建立新增事項的處理器:
- 先去除首尾空白
- 可以在
template
的v-model
後方加上修飾詞.trim
。
- 可以在
- 判斷是否為空值
- 如果去除空白之後為空值,就
return
。
- 如果去除空白之後為空值,就
- 推送資料到陣列
- 如果有值,就
commit
觸發ADD_TODO
,將資料推送到store
裡的todos
陣列。 - 資料應包含:
- 輸入框的
todo
內容 - 預設事項
complete: false
- 輸入框的
- 如果有值,就
- 清空輸入框內容
- 先去除首尾空白
//- components/TodoInput/index.vue
<script>
export default {
data(){
return {
todo: ""
}
},
methods: {
submitHandler(){
if(!this.todo) return
this.$store.commit("ADD_TODO", {
content: this.todo,
complete: false
})
this.todo = ""
}
},
}
</script>
<template src="./template.html"></template>
# 使用「新增資料」模組
建立好「新增資料」的模組之後,要回到 "App.vue" 引入、掛載才能使用。
- 引入:將模組
import
進來。 - 掛載:增加
components
並放入模組名稱。 - 使用:到 "template" 使用模組。
//- App.vue
<template>
<div id="nav">
<router-link :to="{name: 'all'}">全部</router-link> |
<router-link :to="{name: 'active'}">未完成</router-link> |
<router-link :to="{name: 'complete'}">已完成</router-link>
</div>
<TodoInput/> // 使用模組
</template>
<script>
// 引入模組
import TodoInput from "./components/TodoInput.vue/index"
export default {
components: { // 掛載模組
TodoInput
},
// 略 ...
}
</script>
# directive 讓游標 focus 在輸入框
如果希望優化使用者體驗,讓網頁載入後,滑鼠游標直接 focus 在輸入框,而不用透過使用者滑到那裡點擊,可以搭配 Vue 的 directive 自定義指令,讓我們在特定時間點直接操作 DOM。
# 註冊指令
Vue 的自定義指令可註冊於全局或模組,這個範例我們會註冊於全局使用。
由於我們需要在 mounted
後 focus 到輸入框,正好可在 "main.js" 使用官網提供的範例程式碼註冊指令:
//- main.js
const app = Vue.createApp({})
// 注册一个全局自定义指令 `v-focus`
app.directive('focus', {
// 当被绑定的元素挂载到 DOM 中时……
mounted(el) {
// 聚焦元素
el.focus()
}
})
在上面的程式碼中,
- 第一個參數
focus
是這個指令的名稱。 - 第二個參數中,可使用 hook 決定操作的時間點 (例如
mounted
),el
則是被綁定的 DOM 元素。
# 使用指令
和 v-model
、v-bind
相似,自定義指令都會有 v-
前綴。因此使用時,在要使用此指令的 DOM 元素加上 v-focus
,該 DOM 元素就能被操作。
//- components/TodoInput/template.html
<div class="todoInput">
<input
type="text"
placeholder="請輸入待辦事項"
v-model.trim="todo"
@keyup.enter="submitHandler"
v-focus // 加上 v-focus 操作 DOM
/>
</div>
若有需要,使用自定義指令的時候也能傳參數。但這裡的 v-focus
不用傳參數。