代碼
<script src="https://unpkg.com/vue@next"></script>
<div id="todo-list-example">
<form v-on:submit.prevent="addNewTodo">
<label for="new-todo">添加 todo</label>
<input
v-model="newTodoText"
id="new-todo"
placeholder="例如:明天早上跑步"
/>
<button>添加</button>
</form>
<ul>
<todo-item
v-for="(todo, index) in todos"
:key="todo.id"
:title="todo.title"
@remove="todos.splice(index, 1)"
></todo-item>
</ul>
</div>
<script>
const app = Vue.createApp({
data() {
return {
newTodoText: '',
todos: [
{
id: 1,
title: '看電影'
},
{
id: 2,
title: '吃飯'
},
{
id: 3,
title: '上 RUNOOB 學習'
}
],
nextTodoId: 4
}
},
methods: {
addNewTodo() {
this.todos.push({
id: this.nextTodoId++,
title: this.newTodoText
})
this.newTodoText = ''
}
}
})
app.component('todo-item', {
template: `
<li>
{{ title }}
<button @click="$emit('remove')">刪除</button>
</li>
`,
props: ['title'],
emits: ['remove']
})
app.mount('#todo-list-example')
</script>
瀏覽器運行實例
第一階段:form表單
<form v-on:submit.prevent="addNewTodo">
</form>
<form> 標簽用于創建供用戶輸入的 HTML 表單。通常包含一個或多個如下表單元素,如
其中的v-on:submit.prevent="addNewTodo"
,綁定了一個addNewTodo事件,其中的submit.prevent
指在該表單中的任何提交按鈕都可以觸發該事件(比如button
按鈕)。
label
<label for="new-todo">添加 todo</label>
<label> 標簽為 input 元素定義標注(標記)。其中的for="new-todo"
屬性,表示與下面的<input id="new-todo">元素綁定。
當您點擊<label>
元素時,焦點會自動跳到input控件上。例子如下
第二階段:addNewTodo方法
addNewTodo() {
this.todos.push({
id: this.nextTodoId++,
title: this.newTodoText
})
this.newTodoText = ''
}
this.todos.push
- 拿到todos數組,并開始操作
- push() 方法可向數組的末尾添加一個或多個元素,并返回新的長度。
- 注意:?新元素將添加在數組的末尾。
- 注意:?此方法改變數組的長度。
- https://www.runoob.com/jsref/jsref-push.html
id: this.nextTodoId++,
title: this.newTodoText
在數組todos中添加新的元素,
- id的值是(拿到
nextTodoId
的值并且自加1)的值 - title的值是:v-model雙向綁定的
newTodoText
的值
然后,清空newTodoText
的值:this.newTodoText = ''
第三階段:子組件
app.component('todo-item', {
template: `
<li>
{{ title }}
<button @click="$emit('remove')">刪除</button>
</li>
`,
props: ['title'],
emits: ['remove']
})
定義了一個組件todo-item
,接受一個父組件傳入的值title
,通過props: ['title'],
接收,沒有限制和默認值。
組件中還有一個<button>
按鈕,綁定了一個自定義的單擊事件$emit('remove')
,觸發父組件的remove
監聽,
即,當單擊此“刪除”按鈕時,就會觸發父組件:@remove="todos.splice(index, 1)"
的執行。
用emits: ['remove']
來聲明remove
,以免控制臺報錯。
- 自定義事件詳解
- 實戰代碼
- Vue中$emit的用法
- 父組件是使用 props 傳遞數據給子組件,但如果子組件要把數據傳遞回去,就需要使用自定義事件!
- 我們可以使用 v-on 綁定自定義事件
- 子組件可以使用$emit觸發父組件的自定義監聽
核心難點v-for渲染
<todo-item v-for="(todo, index) in todos" :key="todo.id" :title="todo.title"
@remove="todos.splice(index, 1)"></todo-item>
v-for="(todo, index) in todos
,很常見的v-for渲染,里面的index
是列表項的索引值(從0開始)
v-for 指令需要以?todo in todos?形式的特殊語法, todos
是源數據數組并且 todo
是數組元素迭代的別名。
:key="todo.id" :title="todo.title"
,分別賦值,key
是todos
數組里面,id
的值,title是todos
數組里面,title的值。
根據子組件,這里只會渲染title的值。
@remove="todos.splice(index, 1)"
綁定一個自定義事件remove
,當觸發子組件的點擊事件remove
,就會觸發這里的事件,
todos.splice
,拿到數組todos
并開始操作,
splice(index, 1)
,刪掉1個,當前列表索引。(刪掉當前這個li(子組件)的數據)
跑一遍流程:添加數據
- 我單擊“添加tudo”,通過
for="new-todo"
,焦點自動到input輸入框 - 我開始輸入文本“Npcink”,并單擊“添加”按鈕,提交from表單,通過
v-on:submit.prevent="addNewTodo"
全局按鈕觸發事件addNewTodo
- 通過
v-model
雙向綁定,將我輸入的值(npcink)傳給了newTodoText
, addNewTodo
方法下,通過push() 方法新增一條數組,id的值是通過this
獲得nextTodoId
的值并自增的,title的值是通過this拿到newTodoText
的值- 在子組件
todo-item
中,通過{{title}}
展示title的值,通過props: ['title']
拿到父組件的值 - 父組件中通過
v-for
來循環渲染數組內容,通過:title="todo.title"
拿到數組totds
中title
的值,并將其傳給子組件的title
- 子組件
todo-item
將title
渲染出來
跑一遍流程:刪除數據
- 單擊刪除按鈕,通過子組件的
$emit('remove')
觸發父組件的todos.splice(index, 1)
操作 - 刪除了當前行的li數據
參考
- https://www.runoob.com/vue3/vue3-v-for.html
- label標簽中的for屬性:CSDN
- Vue 3 父子組件傳遞數據的幾種通信方式:CSDN
- 列表渲染詳解