说一下 Vue 组件的通信方式都有哪些?(父子组件,兄弟组件,多级嵌套组件等等)

  • 一、父组件向子组件传值
  • 二、子组件向父组件传值
  • 三、兄弟组件传值
  • 四、跨组件

一、父组件向子组件传值

1.1 props 方式:可以是数组或对象,用于接收父组件的数据

<div id="app"><child-component :msg="message" :count="count"></child-component><button @click="count++">点击+1</button>
</div>
<script>const childComponent = {props: {msg: Stringcount: Number},template: `<div><p>{{msg}}</p><p>{{count}}</p><div>`}new Vue({el: '#app',data: {message:'父组件的值',count:0},components:{childComponent}})
</script>

1.2 通过 $parent 获取父组件实例的方法或者属性

这种方式,从严格意义上讲不是值的传递,而是一种 “取” (不推荐直接通过实例进行值的获取)

实例属性 $parent 可以获得父组件的实例,借助实例可以调用父实例中的方法,或者父实例上的属性

<div id="app"><child-component :msg="message" :count="count"></child-component><button @click="count++">点击+1</button>
</div>
<script>//子组件const childComponent = {data:() => ({msg:'',count:null}),methods: {handleClick(){//调用父级实例的方法this.$parent.parentMethods();}}mounted () {// 获取父级实例中的属性this.msg = this.$parent.message;this.count = this.$parent.count;}template: `<div><p @click="handleClick">{{msg}}</p><p>{{count}}</p><div>`}// 父级new Vue({el: '#app',data: {message: '父组件的值',count: 0},methods: {parentMethod () {console.log('我是父级的方法');}}components: {childComponent}})
</script>

1.3 使用修饰符 .sync

修饰符 .sync2.3.0+ 新增,它对 props 起到了一种修饰的作用,使用 .sync 进行修饰的 props ,意味着子组件有修改它的意图,这种情况下它只起到一个标注性作用,有它没它都不会影响逻辑

使用 .sync 修改上边的代码:

// 父组件 List.vue
<template><!-- 这里不写 .sync 也不会影响结果 --><List-item :title.sync="title" @update:title="updataTitle"></List-item>
</template>
<script>import ListItem from "./ListItem";export default {data() {return {title: "我是title",}},components: {ListItem},methods: {updataTitle(res) {this.title = res;}}}
</script>// 子组件 ListItem.vue
<template><div><button @click="handleClick">Click me</button><div>{{title}}</div></div>
</template>
<script>export default {props: {title: String, },methods: {handleClick() {// 子组件向父组件传值this.$emit('update:title', '我要父组件更新 title');}}}
</script>

使用 .sync 向子组件传递多个 props

当我们用一个对象同时设置多个 prop 的时候,也可以将这个 .sync 修饰符和 v-bind 配合使用:

<text-document v-bind.sync="doc"></text-document>

这样会把 doc 对象中的每一个属性(如:title)都作为一个独立的 prop 传进去,然后各自添加用于更新的 v-on 监听器。

二、子组件向父组件传值

2.1 通过事件传值 $emit

使用:

子组件使用 $emit 发送一个自定义事件

父组件使用指令 v-on 监听子组件发送的事件

<div id="app"><child-component @child-event="childEvent"></child-component>
</div>
<script>//子组件const childComponent={data:()=>({msg:'点击发送值到父组件',count:null}),methods:{handleClick(data){this.$emit('child-event','我是子组件传过来的值');}}template:`<div><p @click="handleClick">{{msg}}</p><p>{{count}}</p><div>`}// 父级new Vue({el:'#app',data:{message:'父组件的值',count:0},methods:{childEvent(data){console.log("子组件传过来的值",data);}}components:{childComponent}})
</script>

2.2 通过 $children 获取子组件实例

$parent

2.3 通过 ref 注册子组件引用

虽然存在 prop 和事件,但是有时仍可能需要在 JavaScript 里直接访问一个子组件。为了实现这样的需求,可以使用 ref 特性为某个子组件设置一个 ID 引用,就是一个身份标识

<div id="app"><child-component ref="childComponent"></child-component><button @click="getRefs">获取子组件实例</button>
</div>
<script>//子组件const childComponent={data:()=>({msg:'点击发送值到父组件',count:null}),template:`<div><p @click="handleClick">{{msg}}</p><p>{{count}}</p><div>`}// 父级new Vue({el:'#app',data:{message:'父组件的值',count:0},methods:{getRefs(){console.log("子组件传过来的值",this.$refs.childComponent.msg);}}components:{childComponent}})
</script>

三、兄弟组件传值

3.1 Bus 中央事件总线

非父子组件传值,可以使用一个空的 Vue 实例作为中央事件总线,结合实例方法 $on$emit 使用

注意:

注册的 Bus 要在组件销毁时卸载,否则会多次挂载,造成触发一次但多个响应的情况。

beforeDestroy(){this.$Bus.$off('方法名',value);
}

Bus 定义方式:

  • 1,将 Bus 抽离出来,组件有需要时引入

    // bus.js
    import Vue from 'vue';
    const Bus = new Vue();
    export default Bus;
    
  • 2,将 Bus 挂载到 Vue 根实例的原型上

    import Vue from 'vue';
    Vue.prototype.$bus = new Vue();
    
  • 3,将 Bus 注入到 Vue 根对象上

    import Vue form 'vue';
    const Bus = new Vue();
    new Vue({el:'#app',data:{Bus}
    })
    

    使用例子:

    <div id="app"><child-component ></child-component><child-component-two ></child-component-two>
    </div>
    <script>Vue.prototype.$bus = new Vue();//子组件1 const childComponent={data:()=>({msg:'我是子组件一',sendMsg:'我是子组件一发送的值'}),methods:{handleClick(){this.$Bus.$emit('sendMsg',this.sendMsg);}}template:`<div><p @click="handleClick">{{msg}}</p></p><div>`}//子组件2const childComponentTwo={data:()=>({msg:'我是子组件二',brotherMsg:''}),mounted(){this.$Bus.$on('sendMsg',data=>{this.brotherMsg = data;})},beforeDestroy(){this.$Bus.$off('sendMsg');}template:`<div><p @click="handleClick">{{msg}}</p><p>{{brotherMsg}}</p><div>`}// 父级new Vue({el:'#app',data:{},components:{childComponent,childComponentTwo}})
    </script>
    

四、跨组件

4.1 $attrs$listeners

如果父组件 A 下面有子组件 B,组件 B 下面有组件 C,这时如果组件 A 直接想传递数据给 组件 C,那就行不通了!所以,这时可以使用 $attrs$listeners

Vue 2.4 提供了 $attrs$listeners 来实现能够直接让 组件 A 传递消息给 组件 C

// 组件A
Vue.component('A', {template: `<div><p>this is parent component!</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: {// 执行B子组件触发的事件getChildData(val) {console.log(`这是来自B组件的数据:${val}`);},// 执行C子组件触发的事件getCData(val) {console.log(`这是来自C组件的数据:${val}`);}}
});// 组件B
Vue.component('B', {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: {*     type: String,*     default: ''*   }* }**/props: ['message'],data () {return {mymessage: this.message}},methods: {passData(val){//触发父组件中的事件this.$emit('getChildData', val)}}
});// 组件C
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)}}
});var app = new Vue({el:'#app',template: `<div><A /></div>`
});

4.2 provideinject

熟悉 React 开发的同学对 Context API 肯定不会陌生吧!在 Vue 中也提供了类似的 API 用于组件之间的通信。在父组件中通过 provide 来提供属性,然后在子组件中通过 inject 来注入变量。不论子组件有多深,只要调用了 inject ,那么就可以注入在 provide 中提供的数据,而不是局限于只能从当前父组件的 prop 属性来获取数据,只要在父组件的生命周期内,子组件都可以调用。这和 React 中的 Context API 有没有很相似!

// 定义 parent 组件
Vue.component('parent', {template: `<div><p>this is parent component!</p><child></child></div>`,provide: {for:'test'},data() {return {message: 'hello'}}
});// 定义 child 组件
Vue.component('child', {template: `<div><input type="tet" v-model="mymessage"> </div>`,inject: ['for'],    // 得到父组件传递过来的数据data(){return {mymessage: this.for}},
});const app = new Vue({el: '#app',template: `<div><parent /></div>`
});

上面的实例中,定义了组件 parent 和组件 child,组件 parent 和 组件 child 是父子关系。

  • parent 组件中,通过 provide 属性,以对象的形式向子孙组件暴露了一些属性
  • child 组件中,通过 inject 属性注入了 parent 组件提供的数据,实际这些通过 inject 注入的属性是挂载到 Vue 实例上的,所以在组件内部可以通过 this 来访问

注意:

官网文档提及 provide 和 inject 主要为高阶插件 / 组件库提供用例,并不推荐直接用于应用程序代码中。

4.3 Vuex 状态管理

Vuex 是状态管理工具,实现了项目状态的集中式管理。工具的实现借鉴了 Flux、Redux 和 The Elm Architecture 的模式和概念。当然与其他模式不同的是,Vuex 是专门为 Vue.js 设计的状态管理库,以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新。

【Day13】说一下 Vue 组件的通信方式都有哪些?(父子组件,兄弟组件,多级嵌套组件等等)相关推荐

  1. VUE父子组件之间通信方式

    前言: 在vue组件通信中其中最常见通信方式就是父子组件之中的通性,而父子组件的设定方式在不同情况下又各有不同.最常见的就是父组件为控制组件子组件为视图组件.父组件传递数据给子组件使用,遇到业务逻辑操 ...

  2. vue组件间通信方式

    组件是 vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用. vue组件间的几种通信方式:props.$emit/$on.vuex.$paraent ...

  3. Vue组件间通信方式(详解)

    1. 组件之间的传值通信 组件之间通讯分为三种: 父传子.子传父.兄弟组件之间的通讯 (1)props/$emit 父传子:父组件通过import引入子组件,并注册,在子组件标签上添加要传递的属性,子 ...

  4. Vue 组件间通信方式:自定义事件

    前言 前期分享的测试开发系列!Vue 组件间通信方式汇总,总有一款适合你( 5分钟教程-附项目实战案例 )中介绍了 3 种组件间的通信方法,分别是: props 全局事件总线 消息订阅与发布 今天给大 ...

  5. Vue 组件间通信方式汇总,总有一款适合你( 附项目实战案例 )

    前言 前期分享的 200行纯前端Vue代码!教你写一个专属TodoList[零基础友好] 这个项目案例中使用的组件间通信方式是通过 事件绑定与props 接收来实现的,具体使用方式将在下面进行详细介绍 ...

  6. 【Vue.js】vue2组件间通信方式总结

    目录 一.props传参 1.父组件 ==> 子组件 2.子组件 ==> 父组件 二.组件的自定义事件 三.全局事件总线 四.消息订阅和发布 五.vuex 六.插槽 1.默认插槽 2.具名 ...

  7. vue组件的通信方式

    props/$emit 父子组件通信 父->子props 子->父 $on.$emit 获取父子组件实例 parent.children Ref 获取实例的方式调用组件的属性或者方法 父- ...

  8. vue父子组件进行通信方式

    在vue中如何实现父子组件通信,本篇博客将会详细介绍父子组件通信的流程. 如图所示,父组件向子组件传递数据,可以通过props,子组件向父组件传递数据可以通过触发事件来进行. 一.props 父组件向 ...

  9. 【Vue】Vue中的父子组件通讯以及使用sync同步父子组件数据

    前言: 之前写过一篇文章<在不同场景下Vue组件间的数据交流>,但现在来看,其中关于"父子组件通信"的介绍仍有诸多缺漏或者不当之处, 正好这几天学习了关于用sync修饰 ...

最新文章

  1. 【哲学百科】文艺复兴及唯理主义时期(公元1500~公元1750)
  2. 【小米笔试题】实现一个算法,确定一个字符串的所有字符是否全部不同
  3. python poll_python IO 多路复用 select poll epoll
  4. linux kernel: defconfig和.config
  5. linux centos-6.5,Linux(CentOS 6.5)安装 mysql
  6. java与java ee_Java EE 7社区调查结果!
  7. GSM网络与CDMA网络话务量、基站容量相关计算
  8. webdav 软件_6 款功能强大的工具软件,有一款人人必备
  9. DISC免费性格测试题
  10. 3.2、如何通过JLINK下载程序(附JLINK驱动)
  11. 类微信卡包应用实现(附源码)
  12. rss 是什么?有什么用?
  13. 如何进行微信登录授权测试?
  14. 程序员接私活10个月接30单,纯赚40w!
  15. 《Linux就该这么学》培训笔记_ch00_认识Linux系统和红帽认证
  16. 什么是 JDBC ?
  17. 几款实用的内网穿透工具,推荐
  18. [编程题] 字符迷阵
  19. 【Cocos2d-x 3.x】 动作类Action源码分析
  20. connection and session

热门文章

  1. LeetCode 788. Rotated Digits
  2. s2 理论 第二套题
  3. python-模块-pymysql操作数据库
  4. python-socket客户服务端的传输原理异常关闭的情况
  5. kubernetes日志采集与解析
  6. RPC的负载均衡策略
  7. shiro自定义过滤器
  8. 蓝桥学院2019算法题2.17
  9. 【ES6入门04】:数值扩展
  10. Android短信验证码倒计时