Vue_組件間通信2,使用PubSubJS庫

組件間通信第一種方式:使用標籤傳遞數據,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>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章