組件間通信第一種方式:使用標籤傳遞數據,props聲明接收屬性
組件間通信第二種方式:vue自定義事件,綁定事件監聽和觸發事件
組件間通信第三種方式:消息訂閱和發佈,使用pubsubjs庫
使用ubsub通信的好處就是,兩個組件間的位置沒有任何要求
有三層組件,App–List–Item
在Item中有刪除選中行的功能,在App中訂閱消息,在Item中發佈消息
App.vue
<template>
<div class="todo-container">
<div class="todo-wrap">
<!--<TodoHeader @addTodo="addTodo"/>-->
<TodoHeader ref="header"/>
<TodoList :todos="todos"/>
<TodoFooter :todos="todos" :deleteCompleteTodos="deleteCompleteTodos" :selectAll="selectAll"/>
</div>
</div>
</template>
<!--
綁定事件監聽----訂閱消息
觸發事件----發佈消息
-->
<script>
// 先引入pubsub-js
import PubSub from 'pubsub-js'
import TodoHeader from './components/TodoHeader.vue'
import TodoList from './components/TodoList.vue'
import TodoFooter from './components/TodoFooter.vue'
import storageUtils from './utils/storageUtils'
export default {
data () {
return {
// todos: JSON.parse(localStorage.getItem('todos_key') || '[]') // 讀取localStorage保存的數據
todos: storageUtils.readTodos()
}
},
mounted () { //執行異步代碼
// 給<TodoHeader/>綁定自定義事件(addTodo)監聽
// this.$on('addTodo', this.addTodo) 綁定監聽的目標不對,這裏的this是App組件,而addTodo綁定在TodoHeader上,需要TodoHeader去觸發
this.$refs.header.$on('addTodo', this.addTodo)
// 訂閱消息(deleteTodo),傳遞兩個參數:訂閱的消息名稱和處理函數function(msg,data){}
// 刪除選擇行,需要知道選擇行的下標index,msg沒有用到,其實msg就是deleteTodo,但是不能省略,省略了function(data){},會默認將data當做msg實參
PubSub.subscribe('deleteTodo', (msg, index) => {
this.deleteTodo(index)
})
},
methods: {
addTodo (todo) {
this.todos.unshift(todo)
},
deleteTodo (index) {
this.todos.splice(index, 1)
},
// 刪除所有已完成的
deleteCompleteTodos () {
this.todos = this.todos.filter(todo => !todo.complete)
},
// 全選/全不選
selectAll (isSelectAll) {
this.todos.forEach(todo => {
todo.complete = isSelectAll
})
}
},
watch: {
todos: {
deep: true, // 深度監視
/*handler: function (val) {
// 將數據(json)保存到localStorage
// localStorage.setItem('todos_key', JSON.stringify(val))
storageUtils.saveTodos(val)
}*/
// handler的值應該是一個函數, 且函數應該要有一個形參(接收todos最新的值)
handler: storageUtils.saveTodos,
/*handler: function (todos) {
localStorage.setItem(TODOS_KEY, JSON.stringify(todos))
}*/
}
},
components: {
TodoHeader,
TodoList,
TodoFooter
}
}
</script>
<style>
</style>
Item.vue組件
<template>
<li :style="{background: bgColor}" @mouseenter="handleEnter(true)" @mouseleave="handleEnter(false)">
<label>
<input type="checkbox" v-model="todo.complete"/>
<span>{{todo.title}}</span>
</label>
<button class="btn btn-danger" v-show="isShow" @click="deleteItem">刪除</button>
</li>
</template>
<script>
//要發佈消息,先引入pubsub-js
import PubSub from 'pubsub-js'
export default {
props: {// 指定屬性名和屬性值的類型
todo: Object,
index: Number
},
data () {
return {
bgColor: 'white',
isShow: false
}
},
methods: {
handleEnter (isEnter) {
if(isEnter) { // 進入
this.bgColor = '#cccccc'
this.isShow = true
} else { // 離開
this.bgColor = '#ffffff'
this.isShow = false
}
},
deleteItem () {
// this.deleteTodo(this.index)
// 發佈消息(deleteTodo),刪除選擇行,需要傳遞下標參數,index
PubSub.publish('deleteTodo', this.index)
}
}
}
</script>
<style>
</style>