天天看點

實戰 Vue 之元件通信(父元件與子元件,子元件與父元件)前言一、父元件與子元件通信二、子元件與父元件通信三、其他元件通信

Vue 元件通信

  • 前言
  • 一、父元件與子元件通信
  • 二、子元件與父元件通信
  • 三、其他元件通信

前言

Vue 是單頁面應用,頁面與頁面之間,功能與功能之間,都是一個個的元件構成。元件也有層級結構,父與子關系,子與父關系,兄弟關系等。那麼有關系的元件之間如何通信?将是本文探讨的主題。

一、父元件與子元件通信

父元件向子元件傳值直接通過屬性的方式,子元件通過 props 接收。

父元件調用子元件方法是通過給子元件綁定 ref 擷取子元件執行個體。随後找到子元件的方法并調用。

父元件 TodoList.vue

<template>
  <div>
    <div>
      <input type="text" v-model="text"><button @click="add">添加待辦</button>
      <todo-item
        :taskList="taskList"
        ref="item"
      />
      <button @click="del">删除包含完成的事項</button>
    </div>
  </div>
</template>
<script>
  import TodoItem from './TodoItem.vue';
  export default {
    name: 'TodoList',
    data () {
      return {
        text:"",
        taskList:[]
      }
    },
    components: {
      'todo-item': TodoItem,
    },
    methods: {
      add(){
          this.taskList.push({text:this.text})
      },
      del(){
          //通過ref綁定子元件執行個體,直接調用其方法
        this.taskList = this.$refs.item.del(this.taskList,'完成');
      }
    }
  }
</script>
           

子元件 TodoItem.vue

<template>
  <div>
  <div v-for="(item,index) in taskList">
    <span>{{item.text}}</span>
  </div>
  </div>
</template>
<script>
  export default {
    name: 'TodoItem',
    props:['taskList'],
    methods: {
      //子元件方法,供父元件調用
      del(arr,str){
      return arr.filter((item)=>item.text.indexOf(str)<0)
      }
    }
  }
</script>
           

二、子元件與父元件通信

子元件與父元件通信有 2 種方法。

  1. 子元件通過 props 擷取父元件的方法,并向父元件傳參。

    父元件 TodoList.vue

<template>
  <div>
    <div>
      <button @click="show">顯示清單</button>
      <todo-item
        :taskList="taskList"
        :isShow="isShow"
        :del="del"
      />
      <div>{{tip}}</div>
    </div>
  </div>
</template>
<script>
  import TodoItem from './TodoItem.vue';
  export default {
    name: 'TodoList',
    data () {
      return {
        isShow:false,
        tip:'未删除',
        taskList:[{text:"完成國際會議",done:true},{text:"還未開始國内會議",done:false}]
      }
    },
    components: {
      'todo-item': TodoItem,
    },
    methods: {
      show(){
          this.isShow = !this.isShow
      },
      del(str){
        this.tip = str;
          //通過ref綁定子元件,直接調用其方法
        this.taskList = this.taskList.filter((item)=>item.done)
      }
    }
  }
</script>
           

子元件 TodoItem.vue

<template>
  <div v-if="isShow">
  <div v-for="(item,index) in taskList" >
    <span>{{item.text}}</span>
  </div>
    <button @click="del('删除成功')">删除完成的事項</button>
  </div>
</template>
<script>
  export default {
    name: 'TodoItem',
    props:['taskList','isShow','del']
  }
</script>
           
  1. 子元件通過觸發 $emit 調取父元件的方法,并向父元件傳參。

    父元件 TodoList.vue

<template>
  <div>
    <div>
      <button @click="show">顯示清單</button>
      <todo-item
        :taskList="taskList"
        :isShow="isShow"
        @on-all="del"
      />
      <div>{{tip}}</div>
    </div>
  </div>
</template>
<script>
  import TodoItem from './TodoItem.vue';
  export default {
    name: 'TodoList',
    data () {
      return {
        isShow:false,
        tip:'未删除',
        taskList:[{text:"完成國際會議",done:true},{text:"還未開始國内會議",done:false}]
      }
    },
    components: {
      'todo-item': TodoItem,
    },
    methods: {
      show(){
          this.isShow = !this.isShow
      },
      del(str){
        this.tip = str;
          //通過ref綁定子元件,直接調用其方法
        this.taskList = this.taskList.filter((item)=>item.done)
      }
    }
  }
</script>
           

子元件 TodoItem.vue

<template>
  <div v-if="isShow">
  <div v-for="(item,index) in taskList" >
    <span>{{item.text}}</span>
  </div>
    <button @click="del">删除完成的事項</button>
  </div>
</template>
<script>
  export default {
    name: 'TodoItem',
    props:['taskList','isShow'],
    methods: {
      //通過$emit觸發父元件方法,給父元件傳參
      del(){
        this.$emit('on-all','删除成功');
      }
    }
  }
</script>
           
  1. 差別

通過 props 方式簡寫:

Father 元件

<template>
<div>
  <son :del="del">
</div>
<template>
 export default {
    name: 'Father',
    method:{
     del(){
      console.log("這是父元件的方法");
     }
  }
}
           

Son 元件

<template>
<div @click = "del"></div>
<template>
 export default {
    name: 'Son',
    props:['del'],
}
           

通過 $emit 方式簡寫:

Father 元件

<template>
<div>
  <son @on-del="del">
</div>
<template>
 export default {
    name: 'Father',
    method:{
     del(){
      console.log("這是父元件的方法");
     }
  }
}
           

Son 元件

<template>
<div @click = "$emit('on-del')"></div>
<template>
 export default {
    name: 'Son',
}
           

三、其他元件通信

其他元件通信可使用 Vuex 狀态管理工具。其核心思想是将所有狀态集中管理,一處有變動。其他地方同步更新。可參考 Vuex 使用指南。