Vue_组件间通信3,插槽slot

组件间通信传递消息,很多时候传递的都是数据;
而slot可以传递标签
TodoFooter.vue组件

<template>
  <div class="todo-footer">
    <label>
      <!--<input type="checkbox" v-model="checkAll"/>-->
      <slot name="checkAll"></slot>//设计成插槽
    </label>

    <span>
      <slot name="size"></slot>    //设计成插槽
     <!-- <span>已完成{{completeSize}} / 全部{{todos.length}}</span>-->
    </span>

    <slot name="delete"></slot>    //设计成插槽
   <!-- <button class="btn btn-danger" v-show="completeSize" @click="deleteAllCompleted">清除已完成任务</button>-->
  </div>
</template>

<script>
  export default {

  }
</script>

<style>
</style>

此时TodoFooter组件上的插槽是空的,要在App上进行设计并传递
App.vue组件

<template>
  <div class="todo-container">
    <div class="todo-wrap">
      <!--<TodoHeader @addTodo="addTodo"/>-->
      <TodoHeader ref="header"/>
      <TodoList :todos="todos"/>
      <TodoFooter>
        <input type="checkbox" v-model="checkAll" slot="checkAll"/>
        <span slot="size">已完成{{completeSize}} / 全部{{todos.length}}</span>
        <button class="btn btn-danger" v-show="completeSize" @click="deleteAllCompleted" slot="delete">清除已完成任务</button>
      </TodoFooter>
    </div>
  </div>
</template>

<script>
  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 () {
      // 绑定自定义事件(addTodo)监听
      // this.$on('addTodo',  this.addTodo) 绑定监听的目标不对
      this.$refs.header.$on('addTodo',  this.addTodo)
      // 订阅消息(deleteTodo)
      PubSub.subscribe('deleteTodo', (msg, index) => {
        this.deleteTodo(index)
      })
    },

    //计算属性
    computed: {
      completeSize () {
        return this.todos.reduce((preTotal, todo) => preTotal + (todo.complete?1:0) ,0)
      },

      checkAll: {
        get () { // 决定是否勾选
          return this.completeSize===this.todos.length && this.completeSize>0
        },

        set (value) {// 点击了全选checkbox  value是当前checkbox的选中状态(true/false)
          this.selectAll(value)
        }
      },
    },

    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
        })
      },

      deleteAllCompleted () {
        if(window.confirm('确定清除已完成的吗?')) {
          this.deleteCompleteTodos()
        }
      }
    },

    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>

现在有个问题,就是这些标签是在父组件里编译好了之后再插到TodoFooter里面去;标签中对应的计算属性都应该放到父组件中去

猜你喜欢

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