最全vue组件通讯方式,一定有你不知道的~

vue组件通讯/传值

个人浅见:通讯的意思就是互相联系,我说的你能听到,并且有必要的话能做出回应,组件本身是个具有独立功能的整体,以下便是组件与组件之间的关系和通讯的方式。

一、通讯方式

目前按我了解到的共有以下几种

  • props/$emit
  • $parent/$children/$refs
  • v-bind="$attrs" & v-on="$listener"(2.4+支持)1
  • vuex
  • Vue.$bus(中央事件总线)
  • provide/inject(依赖如属性和方法 祖和后代)2
  • Vue.observable(创建一个store.js 进行监听,2.6+支持)3

二、组件间关系

  • 兄弟组件(毫不相干)

  • 父子组件(父子沟通的方式有很多)

  • 跨层级组件(隔代的祖孙传值)

首先明确一点,就通讯方式而言,支持兄弟组件的必然支持跨层级组件,而支持跨层级组件的必然支持父子组件,故我们只说适合的。

三、应用场景及实例

父子组件

  1. props/$emit(父子,emit可update:[propName])
    prop接的不可修改,若要修改需要调用emit;
    父组件
<template>
    <div>
        <child :lunch='foods' @changeFoods='changeFoods'></child>
    </div>
</template>
<script>
import child from './child.vue';
export default {
    data(){
        return {
            foods:'鱼香肉丝'
        }
    },
    methods:{
        changeFoods(newfoods){
            // 得到孩子的反馈,把饭做出来,把午餐换掉
            this.cook(newfoods);
        },
        cook(foods){
            this.foods = foods;
        }
    }
}
</script>

子组件 child

<template>
    <div>
        <div>爸爸做的午饭:{{lunch}}</div>
        <div @click='changeLunch'>{{lunch}}不好吃,换成红烧肉</div>
    </div>
</template>
<script>
export default {
    props:{
        lunch: String
    },
    methods:{
        changeLunch(){
            // changeFoods 在使用当前组件时需要定义此接参方法。
            this.$emit("changeFoods", '红烧肉');
            // 正经话:如果当前的prop在改变值的时候不需要父组件执行任何其他操作,可以直接选用update更新,外面也不需要定义接事件也就是changeFoods
            // this.$emit("update:lunch", '红烧肉');
        }
    }
}
</script>

  1. $parent/$refs
  • 可在父组件通过this.$refs[refName]获取到子组件的值、方法,可直接调用。
  • 可在子组件直接调用this.$parent获取到父组件实例。
  1. v-bind="$attrs" & v-on="$listener"
    $attrs包含了除prop定义之外的当前组件(父)的属性。
    $listener包含了当前组件的事件,传到子组件中。
    一般可在UI库的二次封装或者定制时使用,减少代码
    如封装element-ui的
<template>
  <div>
    <el-pagination
      :background="background"
      :current-page.sync="currentPage"
      :page-size.sync="pageSize"
      :layout="layout"
      :page-sizes="pageSizes"
      :total="total"
      v-bind="$attrs"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
  </div>
</template>

跨层级组件

  • propsv-bind="$attrs"层层传递 层级多了就不建议使用了,啰嗦。
  • provide & inject 优雅的方式4

祖先组件

data() {
  return {
    name2: "小明",
    age2: 5
  };
},
// 添加依赖数据,它里面定义的数据,子组件可以选择性注入并直接使用。
provide() {
  return {
    doveName: this.name2,
    doveAge: this.age2,
    // 将修改name2和age2的方法,设置为依赖数据
    updateDove: this.updateDove,
  };
},
methods: {
  updateDove(dove) {
    this.name2 = dove.name;
    this.age2 = dove.age;
  },
}

后代组件

// 从父级组件中注入依赖的数据
inject: ["doveName", "doveAge", "updateDove"],
methods: {
  updateData() {
    this.mydoveName = "小红";
    this.mydoveAge = 8;
    // 执行父级组件中的updateDove方法
    this.updateDove({ name: this.mydoveName,age: this.mydoveAge, });
  }
}

兄弟组件

  1. Vue.observable();3
    定义一个store.js
import Vue from 'vue';
const defaultState = () => {
  return Vue.observable({
    name: '路飞'
  });
};
const store = {
  state: defaultState(),
  getters: {
    isData: (key) => store.state[key] && Object.keys(store.state[key]).length > 0
  },
  mutations: {
    setName (data) {
      store.state.name = data;
    }
  }
};

export default store;

使用

import store from '../store';
export default {
    computed(){
        name(){
            // 获取
            store.state.name;
        }
    },
    methods:{
        changeName(name){
            // 修改,响应式的。
            store.mutations.setName(name);
        }
    }
};

标注的在文章都有提到,就不再赘述了,都看到这里了,顺手点个赞呗~


  1. vue-API: $attrs ↩︎

  2. vue-API: provide/inject ↩︎

  3. vue-API: observable ↩︎ ↩︎ ↩︎

  4. (Vue-cli)六、组件间传值(组件间传值&全局状态管理store) ↩︎ ↩︎ ↩︎

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值