天天看點

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裡面去;标簽中對應的計算屬性都應該放到父元件中去