父子孙组件之间的组件通信

  • 面试题:vue组件之间有哪些通信方式呢?

第一种:props+this.$emit:

props:

父组件A通过v-bind绑定数据,传递数据给子组件,子组件用props接收

父组件A:

<template><div class="parent-root"><child class="child"  :message="message"> </child></div>
</template><script>
import child from "@/components/child";
export default {name: "parent",components: { child },data() {return {message:"霸霸的数据"};},</script>

子组件B:

<template><div class="child-root">父组件传来的消息:{{message}}   </div>
</template><script>export default {name: 'child',props: ['message'],</script>

this.$emit:

父组件可以在使用子组件的地方直接用 v-on来监听子组件触发的事件,使用 v-on绑定自定义事件eventName,然后在子组件中使用 $emit(eventName,data)触发事件

父组件A:


子组件B:

第二种:style、class和自定义属性

父组件可以在子组件标签上添加style、class和自定义属性,子组件会合并到自己的根标签身上

父组件A:

<template><div class="parent-root"><child class="child" style="color:#ccc" datd-a="5" :message="message"> </child></div>
</template><script>
import child from "@/components/child";
export default {name: "parent",components: { child },data() {return {message:"霸霸的数据"};},</script>

子组件B:

<template><div class="child-root">父组件传来的消息:{{message}}   </div>
</template><script>export default {name: 'child',props: ['message'],</script>

第三种:this.$attrs、this.$listeners和inheritAttrs

  • 父子组件间的this.$attrs存放了父组件传过来的除style、class、自定义属性和props接收的属性之外的其他属性,通常配合 interitAttrs 选项一起使用
  • 需要注意的是:子组件里使用props接收父组件传来的属性数据之后,该属性就不在this.$attrs里面存放了
  • 父孙之间可以使用this.$attrs传递数据,就不需要在每一层的子组件里都使用v-bind和props层层传递了
  • this.$listeners存放了父组件用v-on(不含 .native 修饰器)的绑定的所有事件,子组件可通过v-bind:$listeners将所有事件传递给后面的孙组件
  • inheritAttrs:默认为true, 会自动在挂载组件元素上属性值,如props声明了属性,则挂载未被声明的属性;false时会关闭自动挂载到组件根元素上属性。注意:这个选项不影响 class 和 style 绑定。

父组件:

<template><div class="parent-root"><child class="child" :name="name" :age="age" :data="data" @change="change" @childEvent="childEvent"> </child><p>孙组件传出来的值:{{text}}</p></div>
</template><script>import child from "@/components/child";export default {name: 'parent',components: {child},data() {return {name:"小明",age:18,text:'',data:"me"};},methods: {//孙组件传出来的事件change(text) {this.text = text;},childEvent(name){console.log("name:",name);}},};
</script>

子组件:

孙组件:

  • inheritAttrs:

    • inheritAttrs为true时:
    • inheritAttrs为false时:

第四种: this.$parent和 this.$children

在组件内部,可以通过$parent$children属性,分别得到当前组件的父组件和子组件实例
结果:

第五种:ProvideInject

父组件实例可以使用Provide向后代组件传递数据,后代组件使用inject来接收数据,

但是需要注意的是,使用这个方法传递的数据不是响应式的,然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。

详细看:https://cn.vuejs.org/v2/api/?#provide-inject

父组件:

子组件:

第六种:v-model

v-model 专门用来做表单元素的当绑定在表单元素上时

  • 当表单为输入表单,v-model最后会生成一个value属性和input事件
  • 当绑定的是一个多选或者单选框,v-model最后生成一个checked属性和change事件

v-model指令实质是一个语法糖,它是value属性和input事件的结合体

<input :value="data" @input="data=$event.target.value" />
<!-- 等同于 -->
<input v-model="data" />

详见:表单输入绑定

$event.target.value
获取触发事件的target,就是触发事件的DOM元素的value

**当v-model绑定在组件上时 ( 等同于prop+this.$emit ) **

  • 父组件通过v-model传递值给子组件时,会自动传递一个value的prop属性,在子组件中通过this.$emit(‘input’,val)自动修改v-model绑定的值
<!-- 父组件 -->
<template> <Child v-model="value" />
</template>
等同于:
<template> <Child :value="value" @ />
</template>
<!-- 子组件 -->
<template><input v-model="input" />
</template>
<script>
export default {props: {value: String,},model: {prop: 'value',        // 指定 v-model 要绑定的参数叫什么名字,来自于 props 中定义的参数event: 'change', // 指定要触发的事件名字,将被用于 $emit},computed: {input: {// 这里的计算属性使用了 getter、setter,可以简化代码// 可参见链接 https://cn.vuejs.org/v2/guide/computed.html#%E8%AE%A1%E7%AE%97%E5%B1%9E%E6%80%A7%E7%9A%84-setterget() {return this.value;},set(val) {this.$emit('change', val); // 触发}}}
}
</script>

第七种:.sync修饰符

v-model的作用类似,用于双向绑定,不同点在于v-model只能针对一个数据进行双向绑定 ,只针对input事件的value值进行绑定,而sync修饰符没有限制

示例

<!-- 父组件 -->
<template><div id="app"><Numbers :num1.sync="n1" :num2.sync="n2" /><!-- 等同于 --><Numbers:num1="n1"@update:num1="n1 = $event":num2="n2"@update:num2="n2 = $event"/></div>
</template><script>
import Numbers from "./components/Numbers.vue";export default {components: {Numbers,},data() {return {n1: 0,n2: 0,};},
};
</script>

第八种:$ref

父组件可以通过ref获取到子组件的实例

  • 不过这种做法一般是不得已的时候才会使用ref,因为ref,因为ref,因为ref会动用真实的DOM操作,与vue的减少对DOM元素的手动操作的理念有所违背

不局限于父子孙层级关系的跨组件通信:

(兄弟与兄弟)

第一种:vuex

适用于大型项目的数据仓库

第二种:store模式

适用于中小型项目的数据仓库

// store.js
const store = {loginUser: ...,setting: ...
}// compA
const compA = {data(){return {loginUser: store.loginUser}}
}// compB
const compB = {data(){return {setting: store.setting,loginUser: store.loginUser}}
}

第三种:eventbus

组件通知事件总线发生了某件事,事件总线通知其他监听该事件的所有组件运行某个函数 (发布订阅模式)【vue3.0好像不支持事件总线的方式了?】

// 发送消息
EventBus.$emit(channel: string, callback(payload1,…))// 监听接收消息
EventBus.$on(channel: string, callback(payload1,…))

它的工作原理是发布/订阅方法,通常称为 Pub/Sub

var EventBus = new Vue();
Object.defineProperties(Vue.prototype, {$bus: {get: function () {return EventBus}}
})

在这个特定的总线中使用两个方法 $on$emit 。一个用于创建发出的事件,它就是 $emit ;另一个用于订阅 $on

var EventBus = new Vue();
this.$bus.$emit('nameOfEvent', { ... pass some event data ...});
this.$bus.$on('nameOfEvent',($event) => {// ...
})

然后我们可以在某个Vue页面使用 this.$bus.$emit("sendMsg", '我是web秀');,另一个Vue页面使用

this.$bus.$on('updateMessage', function(value) {console.log(value); // 我是web秀
})

同时也可以使用this.$bus.$off('sendMsg')来移除事件监听。

第四种:router

如果一个组件改变了地址栏,所有监听地址栏的组件都会做出相应反应

最常见的场景就是通过点击router-link组件改变了地址,router-view组件就渲染其他内容

笔记相关的代码:

父组件:

<template><div class="parent-root"><childclass="child":name="name":age="age":data="data"@change="change"@childEvent="childEvent"></child><p>孙组件传出来的值:{{ text }}</p></div>
</template>
<script>
import child from "@/components/child";
export default {name: "parent",components: { child},provide: {foo: "bar",},data() {return {name: "小明",age: 18,text: "",data: "me",};},computed: {},created() {},methods: {//孙组件传出来的事件change(text) {this.text = text;},childEvent(name) {console.log("name:", name);},},
};
</script><style scoped lang="less">
.parent-root {padding: 20px;font-size: 16px;position: absolute;p {margin-bottom: 10px;}
}
</style>

子组件:

<template><div class="child-root"><grandchild v-bind="$attrs" v-on="$listeners"> </grandchild><br /><button @click="childEvent">子组件的childEvent</button><br />子组件用props接收了data的数据: {{ data }}</div>
</template><script>
import grandchild from "@/components/grandchild";
export default {name: "child",components: { grandchild },inject: ["foo"], props: ["data"],//inheritAttrs://默认为true, 会自动在挂载组件元素上属性值,如props声明了属性,则挂载未被声明的属性//为false时会关闭自动挂载到组件根元素上属性inheritAttrs: false,data() {return {};},computed: {},created() {console.log(this.foo);console.log("$attrs:", this.$attrs, "$listeners:", this.$listeners); //$attrs: { "name": "小明", "age": 18 },这里不会输出"class":"child"},mounted() {console.log("parent:", this.$parent, "children:", this.$children);},methods: {childEvent() {console.log("child的data:", this.data);},},
};
</script><style scoped lang="less">
.child-root {border: 1px solid #ccc;
}
</style>

孙组件:

<template><div class="grandchild-root"><p>name:{{name}}</p><p>age:{{age}}</p><p>data:{{data}}</p><button @click="bindChange">孙子点击传给爷爷</button></div>
</template>
<script>export default {name: 'grandchild',components: {},props: {name: {type: String,default: ''},age:{type: Number,default: null},data:{type: String,default: null}},methods: {bindChange() {let text = '爷爷,您好'this.$emit('change',text);}},};
</script>

整理笔记看的相关文章:

vue的通信:

https://blog.csdn.net/zhoulu001/article/details/79548350

https://blog.csdn.net/Dobility/article/details/110147985

https://blog.csdn.net/weixin_42211816/article/details/116529864

v-model原理:

https://blog.csdn.net/yun_hou/article/details/86313212

https://blog.csdn.net/weixin_42380658/article/details/86568666

修饰符:

https://blog.csdn.net/qq_29468573/article/details/80771625

事件总线:

https://blog.csdn.net/i168wintop/article/details/95107935

vue的父子孙之间组件通信和兄弟之间的组件通信相关推荐

  1. Vue第二天学习总结—— Vue全家桶之组件化开发(组件化开发思想、组件注册、Vue调试工具用法、组件间数据交互传递、组件插槽、基于组件的案例——购物车)

    (一) 组件化开发思想 1. 现实中的组件化思想体现 组件化即是对某些可以进行复用的功能进行封装的标准化工作 标准:要想组件能够成功组合在一起,每个组件必须要有标准 分治:将不同的功能封装到不同的组件 ...

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

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

  3. Vue中父子及非父子组件之间的通信方法

    Vue中父子及非父子组件之间的通信方法 父子组件之间的通信方法 父级->子级通信 (依赖单向数据绑定+props实现) Vue.component('Father', { //注册了含有data ...

  4. vue的父子组件之间的通信详解

    vue的父子组件之间的通信详解 一.父组件给子组件传值 父组件引入子组件,并对子组件进行监听 <!-- 父组件 --><template><div><h1&g ...

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

    情景 父组件有一个 btnList 数组,里面存放着按钮的名称和按钮的id,现在要把这个数组传入到子组件中进行渲染. 子组件渲染出按钮后,点击按钮,父组件的 h1 标签中会显示出当前点击的按钮是哪一个 ...

  6. VUE非父子组件之间通信的几种方式

    一.使用广播的方式$emit(), $on() 1.创建js文件 import Vue from 'vue'export default new Vue() 组件A import bus from ' ...

  7. vue中非父子组件通信

    在上一篇博客中,我们总结了父子组件通信方式有:props + emit.这里我们将总结一下,非父子组件通信方式,这里还不涉及到Vuex. 如果存在祖孙组件,我们可以通过Provide和Inject进行 ...

  8. 实现非父子之间通信,兄弟组件之间的数据传递--eventBus

    vue中,组件传值的方法常见的也就那几种, 1.父组件向子组件传值,用props 属性, 2.子组件主要通过事件传递数据给父组件子向父传数据可以用$emit触发传,但是这种方法无法实现兄弟组件直接传数 ...

  9. Vue中父子之间的通信

    在学习vue中,往往会碰到父子组件之间的通信问题,用一张图来简单解释下父子之间如何通信 由图可以知道 父组件传递参数给子组件 子组件通过props接收参数 父子通信 代码演示: <!DOCTYP ...

最新文章

  1. Linux内核编译过程分析
  2. 【Spring】12、Spring Security 四种使用方式
  3. 结束oracle import,Oracle 结束 imp/exp 和 expdp/impdp 进程的正确方法
  4. Windows 运行... 可执行的命令
  5. php后台如何避免用户直接进入方法
  6. 深度系统安装移动硬盘启动_深度系统如何安装_电脑知识
  7. 【JZOJ3824】【NOIP2014模拟9.9】渴
  8. 黄俊:电商系统的一些心得分享
  9. 设置windows自动登录
  10. android随机抽奖代码_手机随机数字抽奖器APP下载-手机随机数字抽奖器最新版下载 v2.0.3安卓版-都去下载...
  11. FTPSFTP的基本命令
  12. PLSQL 教程 简单上手教程
  13. 中继器制作联动下拉列表
  14. Python 蓝凌OA任意文件读取批量扫描 poc编写
  15. 使用阿里云对象存储oos遇到跨域访问的问题
  16. 未来小七:AI缩小教育差距,让孩子快乐成长
  17. 苹果电脑可以装windows系统吗_iPhone 可以装 windows 了,想不想试试?
  18. 基于51单片机的宠物自动猫粮狗粮喂养机proteus仿真原理图PCB
  19. 如何判断是不是个maven项目
  20. 新冠疫情中的区块链应用

热门文章

  1. 《现代命令行工具指南》15.表情符号:在命令行中查找表情符号 - emoj
  2. 电子烟软件测试项目清单,电子烟分析测试报告-COSH.PDF
  3. windows强制复制不计算机,Win10复制粘贴功能用不了的修复方法
  4. Git快捷删除本地已经合并到master的分支
  5. springboot + Mybatis +前端layui 项目总结(一)
  6. 机器学习入门(九):非监督学习:5种聚类算法+2种评估模型
  7. 利用Gitee搭建私人仓库-https篇
  8. php 海关对接 进口商品_海关总署公布跨境进口统一版系统对接事项
  9. 阿里云emas远程真机使用指南
  10. CorelDRAW使用图文教程电子书