天天看點

Vue入門011- TodoList案例(元件自定義事件)

在TodoList案例(本地存儲)案例的基礎上。

Vue入門009- TodoList案例(本地存儲)

把App.vue 和 MyHeade.vue 改成元件自定義事件的方式來通訊

把App.vue 和 MyFooter.vue 改成元件自定義事件的方式來通訊

App.vue代碼

<template>
	<div id="root">
		<div class="todo-container">
			<div class="todo-wrap">
				<MyHeader @addTodo="addTodo"/>
				<MyList :todos="todos" :checkTodo="checkTodo" :deleteTodo="deleteTodo"/>
				<MyFooter :todos="todos" @checkAllTodo="checkAllTodo" @clearAllTodo="clearAllTodo"/>
			</div>
		</div>
	</div>
</template>

<script>
	import MyHeader from './components/MyHeader'
	import MyList from './components/MyList'
	import MyFooter from './components/MyFooter.vue'

	export default {
		name:'App',
		components:{MyHeader,MyList,MyFooter},
		data() {
			return {
				//由于todos是MyHeader元件和MyFooter元件都在使用,是以放在App中(狀态提升)
				todos:JSON.parse(localStorage.getItem('todos')) || []
			}
		},
		methods: {
			//添加一個todo
			addTodo(todoObj){
				this.todos.unshift(todoObj)
			},
			//勾選or取消勾選一個todo
			checkTodo(id){
				this.todos.forEach((todo)=>{
					if(todo.id === id) todo.done = !todo.done
				})
			},
			//删除一個todo
			deleteTodo(id){
				this.todos = this.todos.filter( todo => todo.id !== id )
			},
			//全選or取消全選
			checkAllTodo(done){
				this.todos.forEach((todo)=>{
					todo.done = done
				})
			},
			//清除所有已經完成的todo
			clearAllTodo(){
				this.todos = this.todos.filter((todo)=>{
					return !todo.done
				})
			}
		},
		watch: {
			todos:{
				deep:true,
				handler(value){
					localStorage.setItem('todos',JSON.stringify(value))
				}
			}
		},
	}
</script>

<style>
	/*base*/
	...
</style>
           

代碼解釋

第5行 <MyHeader @addTodo="addTodo"/>

給MyHeader綁定自定義事件addTodo,回調方法addTodo

第7行 <MyFooter :todos="todos" @checkAllTodo="checkAllTodo" @clearAllTodo="clearAllTodo"/>

給MyFooter綁定自定義事件checkAllTodo,回調方法checkAllTodo

給MyFooter綁定自定義事件clearAllTodo,回調方法clearAllTodo

注意:這裡的事件名和回調函數名稱一緻,其實不一樣也無所謂的

MyHeader.vue代碼

<template>
	<div class="todo-header">
		<input type="text" placeholder="請輸入你的任務名稱,按Enter鍵确認" v-model="title" @keyup.enter="add"/>
	</div>
</template>

<script>
	import {nanoid} from 'nanoid'
	export default {
		name:'MyHeader',
		data() {
			return {
				//收集使用者輸入的title
				title:''
			}
		},
		methods: {
			add(){
				//校驗資料
				if(!this.title.trim()) return alert('輸入不能為空')
				//将使用者的輸入包裝成一個todo對象
				const todoObj = {id:nanoid(),title:this.title,done:false}
				//通知App元件去添加一個todo對象
				this.$emit('addTodo',todoObj,1,2,3)
				//清空輸入
				this.title = ''
			}
		},
	}
</script>

<style scoped>
	/*header*/
	...
</style>           

解碼解釋

代碼24行 this.$emit('addTodo',todoObj,1,2,3) 通知App元件去添加一個todo對象,其實就是觸發MyHeader身上的自定義事件addTodo,隻不過這個事件是父元件綁定過來的,并且回調也再父元件裡

MyFooter.vue代碼

<template>
	<div class="todo-footer" v-show="total">
		<label>
			<!-- <input type="checkbox" :checked="isAll" @change="checkAll"/> -->
			<input type="checkbox" v-model="isAll"/>
		</label>
		<span>
			<span>已完成{{doneTotal}}</span> / 全部{{total}}
		</span>
		<button class="btn btn-danger" @click="clearAll">清除已完成任務</button>
	</div>
</template>

<script>
	export default {
		name:'MyFooter',
		props:['todos'],
		computed: {
			//總數
			total(){
				return this.todos.length
			},
			//已完成數
			doneTotal(){
				//此處使用reduce方法做條件統計
				/* const x = this.todos.reduce((pre,current)=>{
					console.log('@',pre,current)
					return pre + (current.done ? 1 : 0)
				},0) */
				//簡寫
				return this.todos.reduce((pre,todo)=> pre + (todo.done ? 1 : 0) ,0)
			},
			//控制全選框
			isAll:{
				//全選框是否勾選
				get(){
					return this.doneTotal === this.total && this.total > 0
				},
				//isAll被修改時set被調用
				set(value){
					// this.checkAllTodo(value)
					this.$emit('checkAllTodo',value)
				}
			}
		},
		methods: {
			/* checkAll(e){
				this.checkAllTodo(e.target.checked)
			} */
			//清空所有已完成
			clearAll(){
				// this.clearAllTodo()
				this.$emit('clearAllTodo')
			}
		},
	}
</script>

<style scoped>
	/*footer*/
	...
</style>           

代碼42行 this.$emit('checkAllTodo',value) 觸發自定義事件checkAllTodo

代碼53行 this.$emit('clearAllTodo') 觸發自定義事件clearAllTodo

時刻要清楚,事件是父元件綁定上來的,對應回調肯定在父元件中

代碼摘錄于尚矽谷Vue學習課件

繼續閱讀