目录

前言

一、props 和 $emit

二、$attrs 和 $listeners

三、eventBus——$emit 和 $on

四、provide 和 inject(跨组件通信)

1、认识 provide 和 inject

2、provide 和 inject 的使用

(1)、传递普通的数据

(2)、传递异步的数据

五、使用 vue-ref 插件结合 provide 和 inject 获取组件的实例

六、v-model

七、$parent、$children 和 $refs

1、$children 和 $rfes

2、$parent(不建议使用)

3、案例

八、vuex 处理组件之间的数据交互


前言

参考:vue组件之间8种组件通信方式总结

vue 组件之间的通信方式大概有 9 种:

  • props 和 $emit
  • $refs
  • $attrs 和 $listeners
  • eventBus
  • provide 和 inject
  • v-model
  • $parent 和 $children
  • boradcast 和 dispatch
  • vuex 处理组件之间的数据交互

一、props 和 $emit

父传子——props

子传父——$emit

Vue.component("child", {data() {return {mymessage: this.message,};},template: `<div><input type="text" v-model="mymessage" @input="passData(mymessage)"> </div>`,props: ["message"], //得到父组件传递过来的数据methods: {passData(val) {//触发父组件中的事件this.$emit("getChildData", val);},},
});Vue.component("parent", {template: `<div><p>this is parent compoent!</p><child :message="message" v-on:getChildData="getChildData"></child></div>`,data() {return {message: "hello",};},methods: {//执行子组件触发的事件getChildData(val) {console.log(val);},},
});
var app = new Vue({el: "#app",template: `<div><parent></parent></div>`,
});

上述代码中,父组件传递了message数据给子组件,并且通过v-on绑定了一个getChildData事件来监听子组件的触发事件;子组件通过props得到相关的message数据,最后通过this.$emit触发了getChildData事件。

假设有这么一个场景:私人订制一只宠物。父组件是具有定制宠物的给用户的功能,子组件具有决定定制什么宠物的功能。那么此时,子组件在调用父组件的定制宠物的给用户的功能时,就需要给选定一种宠物,这就需要传递第二个参数了。

二、$attrs 和 $listeners

问题:如果父组件A下面有子组件B,组件B下面有组件C,这时如果组件A想传递数据给组件C怎么办呢?

可以借助 $attrs 和 $listeners 来实现 “隔代传值”。

Vue.component("C", {template: `<div><input type="text" v-model="$attrs.messagec" @input="passCData($attrs.messagec)"> </div>`,methods: {passCData(val) {//触发父组件A中的事件this.$emit("getCData", val);},},
});Vue.component("B", {data() {return {mymessage: this.message,};},template: `<div><input type="text" v-model="mymessage" @input="passData(mymessage)"> <!-- C组件中能直接触发getCData的原因在于 B组件调用C组件时 使用 v-on 绑定了$listeners 属性 --><!-- 通过v-bind 绑定$attrs属性,C组件可以直接获取到A组件中传递下来的props(除了B组件中props声明的) --><C v-bind="$attrs" v-on="$listeners"></C></div>`,props: ["message"], //得到父组件传递过来的数据methods: {passData(val) {//触发父组件中的事件this.$emit("getChildData", val);},},
});Vue.component("A", {template: `<div><p>this is parent compoent!</p><B :messagec="messagec" :message="message" v-on:getCData="getCData" v-on:getChildData="getChildData(message)"></B></div>`,data() {return {message: "hello",messagec: "hello c", //传递给c组件的数据};},methods: {getChildData(val) {console.log("这是来自B组件的数据");},//执行C子组件触发的事件getCData(val) {console.log("这是来自C组件的数据:" + val);},},
});var app = new Vue({el: "#app",template: `<div><A></A></div>`,
});

三、eventBus——$emit 和 $on

这种方法通过一个空的Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件,巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级。

$emit 和 $on 的实现:新建一个Vue事件bus对象,然后通过bus.$emit触发事件,bus.$on监听触发的事件。

Vue.component("brother1", {data() {return {mymessage: "hello brother1",};},template: `<div><p>this is brother1 compoent!</p><input type="text" v-model="mymessage" @input="passData(mymessage)"> </div>`,methods: {passData(val) {//触发全局事件globalEventbus.$emit("globalEvent", val);},},
});Vue.component("brother2", {template: `<div><p>this is brother2 compoent!</p><p>brother1传递过来的数据:{{brothermessage}}</p></div>`,data() {return {mymessage: "hello brother2",brothermessage: "",};},mounted() {//绑定全局事件globalEventbus.$on("globalEvent", (val) => {this.brothermessage = val;});},
});//中央事件总线
var bus = new Vue();var app = new Vue({el: "#app",template: `<div><brother1></brother1><brother2></brother2></div>`,
});

四、provide 和 inject(跨组件通信)

provide 和 inject 是成对出现的。在上层组件中通过 provide 来提供变量,然后在下层组件中通过 inject 来注入变量。用于父组件向子孙组件传递数据。

1、认识 provide 和 inject

provide 选项可以是:

  • 一个对象。
  • 一个函数,该函数的返回值是一个对象。

inject 选项可以是:

  • 一个字符串数组。
  • 一个对象。此时:
    • 对象的 key 是当前组件将要使用的变量名。
    • 对象的 value 可以是:
      • provide 里提供的属性,以及。
      • 一个对象,该对象包括两个属性:
        • from 属性:provide 里提供的属性。
        • default 属性:默认值。

provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。

2、provide 和 inject 的使用

(1)、传递普通的数据

父组件:

<template><s-p-r-v2 />
</template>
<script>import SPRV2 from './components/s-p-r-v2.vue'export default {components: {SPRV2},provide() {return {str: 'hello'}}}
</script>

子组件:

<template><!-- <div>{{ str }}</div> --><div>{{ msg }}</div>
</template>
<script>export default {// 方式一// inject: ['str'],// 方式二// inject: {msg: 'str' }// 方式三inject: {msg: {from: 'str',default: ''}}}
</script>

(2)、传递异步的数据

父组件:

<template><s-p-r-v2 />
</template>
<script>import SPRV2 from './components/s-p-r-v2.vue'export default {components: {SPRV2},provide() {return {flag: () => this.flag}},data() {return {flag: false}},mounted() {setTimeout(() => {this.flag = true}, 3000)}}
</script>

子组件:

<template><div>{{ newStatus }}</div>
</template>
<script>export default {// 方式一// inject: ['flag'],// 方式二// inject: { status: 'flag' },// 方式三inject: {status: {from: 'flag',default: () => false}},computed: {newStatus() {// return this.flag()return this.status()}}}
</script>

【注意】小型状态管理,可以使用 provide/inject。大型状态管理,建议使用 vuex。

【扩展】

vue中的provide和inject

vue中provide和inject使用

五、使用 vue-ref 插件结合 provide 和 inject 获取组件的实例

可以使用 ref 来获取跨级组件实例。

安装:vue-ref

npm i vue-ref -S

然后,在main.js中写入下面的代码:

import ref from 'vue-ref';
Vue.use(ref, { name: 'getRef' });// 这里之所以重命名,是为了避免与vue预留的v-ref指令冲突

假设,已经创建了vue实例,并且在其中引入了index.vue,或者配置好了vue-router。

// index.vue
<template><div><ChildrenA /></div>
</template>
<script>
import ChildrenA from "./component/ChildrenA1";
export default {components: {ChildrenA}
};
</script>

子组件:A

// ChildrenA1.vue
<template><div><h1>A 结点</h1><button @click="getEH3Ref">获取E h3 Ref</button><ChildrenC /></div>
</template>
<script>
import ChildrenC from "./ChildrenC2";
export default {components: {ChildrenC,},provide() {return {/*** @name:子组件的组件名称* @ref:子组件中 ref 的名字* * 主动通知——缓存子组件的 ref**/ setChildrenRef: (name, ref) => {this[name] = ref;},/*** @name:其他子组件的组件名称* * 主动获取——获取其他子组件的实例**/ getChildrenRef: name => {return this[name];},// 获取上层组件的实例getRef: () => {return this;}};},methods: {getEH3Ref() {console.log(this.childrenE);}}
};
</script>

子组件的子组件:E

// childrenE.vue
<template><div><h3 v-getRef="c => setChildrenRef('childrenE', c)">E 结点</h3><button @click="getARef">获取组件 A 的实例</button><button @click="getHRef">获取组件 H 的实例</button></div>
</template>
<script>
export default {inject: {setChildrenRef: {default: null},getParentRef: {from: "getRef",default: () => {}},getParentChildrenRef: {from: "getChildrenRef",default: () => {}}},methods: {// 获取上层组件的实例getARef() {console.log(this.getParentRef());},// 获取其他子组件的实例getHRef() {console.log(this.getParentChildrenRef("childrenH"));}}
};
</script>

子组件的子组件:H

<template><div><h3>H 结点</h3></div>
</template>

六、v-model

父组件通过v-model传递值给子组件时,会自动传递一个value的prop属性,在子组件中通过this.$emit(‘input’,val)自动修改v-model绑定的值。

Vue.component("child", {props: {value: String, //v-model会自动传递一个字段为value的prop属性},data() {return {mymessage: this.value,};},methods: {changeValue() {this.$emit("input", this.mymessage); //通过如此调用可以改变父组件上v-model绑定的值},},template: `<div><input type="text" v-model="mymessage" @change="changeValue"> </div>`,
});Vue.component("parent", {template: `<div><p>this is parent compoent!</p><p>{{message}}</p><child v-model="message"></child></div>`,data() {return {message: "hello",};},
});var app = new Vue({el: "#app",template: `<div><parent></parent></div>`,
});

注意:在组件上使用 v-model

七、$parent、$children 和 $refs

有时候我们需要父组件直接访问子组件、子组件直接访问父组件,或者子组件访问根组件:

  • 父组件访问子组件:使用 $children 或 $refs
  • 子组件访问父组件:使用 $parent

1、$children 和 $rfes

this.$children 是一个数组类型,它包含了所有子组件对象,可以通过循环它拿到所有子组件数据。

比如:this.$children[2] 来拿到第三个子组件的数据。
但是这么做有一个问题:比如开发时突然在这三个子组件中又插入了一个子组件(可能相同,也可能不同),这时候 this.$children[2] 就不再是我们需要的了。怎么办呢?使用 $rfes。

2、$parent(不建议使用)

$parent 是当前组件树的根 Vue 实例。如果当前实例没有父实例,此实例将会是其自己。该属性只读。

不建议使用 $parent,因为它的耦合度很高,容易发生一些错误。

3、案例

Vue.component("child", {props: {value: String, //v-model会自动传递一个字段为value的prop属性},data() {return {mymessage: this.value,};},methods: {changeValue() {this.$parent.message = this.mymessage; //通过如此调用可以改变父组件的值},},template: `<div><input type="text" v-model="mymessage" @change="changeValue"> </div>`,
});Vue.component("parent", {template: `<div><p>this is parent compoent!</p><button @click="changeChildValue">test</button ><child></child></div>`,methods: {changeChildValue() {this.$children[0].mymessage = "hello";},},data() {return {message: "hello",};},
});var app = new Vue({el: "#app",template: `<div><parent></parent></div>`,
});

八、vuex 处理组件之间的数据交互

如果业务逻辑复杂,很多组件之间需要同时处理一些公共的数据,这个时候才有上面这一些方法可能不利于项目的维护,vuex的做法就是将这一些公共的数据抽离出来,然后其他组件就可以对这个公共数据进行读写操作,这样达到了解耦的目的。

详情可参考:Vuex

vue 组件之间的通信相关推荐

  1. [vue] vue组件之间的通信都有哪些?

    [vue] vue组件之间的通信都有哪些? 父子Coms: 1/2/3 ..兄弟Coms: 4/5跨级Coms: 4/5/6/7props$emit/$on( $parents/$children ) ...

  2. 描述vue组件之间的通信

    ##描述 vue组件之间的通信 详细易懂,转自https://www.cnblogs.com/barryzhang/p/10566515.html

  3. 第十节:实现vue组件之间的通信

    这一节我们还是来继续介绍组件:组件之间如何通信. 第九节我们在介绍组件知识的时候,提到过组件可以接受参数props,这其实就是组件之间的一种通信方式:父组件→子组件传递数据. 父组件→子组件 那我们还 ...

  4. Vue组件之间的通信-父传子-子传父

    文章目录 Vue的组件嵌套 Vue组件间通信 1.父组件传递给子组件 1.1数组的方式 1.2对象的方式 2.子组件传递给父组件 Vue的组件嵌套 前面我们是将所有的逻辑放到一个App.vue中: 在 ...

  5. 【组件】Vue组件之间的通信父传子 | 子传父

  6. vue中子组件和子组件之间怎么通信_vue.js组件之间如何通信?

    vue.js组件之间如何通信?下面本篇文章就来给大家介绍一下Vue.js组件间通信方式.有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助. 平时在使用Vue框架的业务开发中,组件不仅仅要 ...

  7. vue/父子组件之间的通信

    父子组件之间的通信 父组件绑定数据在组件上子组件props属性接收 父组件内的data属性中待传的数据data1 => <cpn :data2="data1">& ...

  8. Vue非父子组件之间的通信

    文章目录 非父子组件的通信 1.Provide和Inject 1.1基本使用 1.2处理响应式数据(了解) 2.全局事件总线 非父子组件的通信 此篇讲解的是, 在学习状态管理之前, 非父子间通信的方案 ...

  9. VUE 2.0 父子组件之间的通信

    父组件是通过props属性给子组件通信的来看下代码: 父组件: <parent><child :child-com="content"></child ...

最新文章

  1. 计算机操作系统课设总结,计算机操作系统课程设计
  2. 从字母数字字符串中提取数字
  3. Oracle010316,安装oracle后登录时出现 ERROR: ORA-01031 insufficient privileges
  4. 保存工具条菜单有bug吗?
  5. 【codevs2370】小机房的树,RMQ求LCA
  6. 20191102每日一句
  7. 2020年30种最佳的免费网页爬虫软件
  8. 调查丨融资企业数量不如出台政策多,产业区块链破局路在何方?
  9. 一种基于A* 算法的动态多路径规划算法
  10. 送给80、90后的人生经典语录,别再孩子气了
  11. lambda的peek(流元素操作),filter(过滤),map(映射),limit(截断),skip(跳过),collect,distinct(去重)函数使用
  12. 修改MySQL数据库的密码
  13. 动手实现 Bahdanau 注意力模型
  14. 魅族MX4安装Ubuntu Touch系统
  15. 【转载】JVM能够开启多少线程
  16. 不要虚荣心太强,要踏实肯干
  17. linux下网卡测速,Linux下 网卡测速
  18. Tabu Search求解作业车间调度问题(Job Shop Scheduling)-附Java代码
  19. BA无标度网络(一):规则网络生成
  20. MATLAB求两条正弦波波形的相位差

热门文章

  1. Ubuntu中安装和使用miniconda
  2. 基于单片机电子指南针系统设计(毕业)-全套资料分享
  3. python获取随机字符串_python生成随机字符串
  4. qt android安装在哪,Qt On Android开发环境安装、配置
  5. web3:智能合约-虚拟机(EVM、HVM、WASM、MOVE)
  6. iOS开发之文件管理
  7. 旋转矩阵的构造和螺旋三角阵的构造
  8. PHP连接MySQL函数总结
  9. 浅谈工业级4G通信模块适配流程---一个做通信模块十多年的老工程师的经验之谈
  10. 错误: 未能完成程序集的安装(hr = 0x8007000b)。探测终止。