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>

猜你喜欢

转载自blog.csdn.net/mrcool2012/article/details/104492741