天天看点

实战 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 使用指南。