Vue 父子组件间的通信

简介: 前言 在 Vue 项目中父子组件的通信是非常常见的,最近做项目的时候发现对这方面的知识还不怎么熟练,在这边做一下笔记,系统学习一下吧。

前言 在 Vue 项目中父子组件的通信是非常常见的,最近做项目的时候发现对这方面的知识还不怎么熟练,在这边做一下笔记,系统学习一下吧。

1 父组件传值给子组件

1.1 传值写法

父组件传值给子组件,这个就比较常见了,直接用 props 就可以了。但是就算是 props 子组件那边也有三种写法,如下面代码所示:
父组件

```<!-- 两种情况 --> <!--静态传值--> <child name="xhm"></child> <!--动态传值--> <child :name="userName"></child> ```

子组件


// 1 简单粗暴就给个名称的情况
props:['name'],
// 2 给个名称顺便指定个类型,如果父组件传递过来的值类型不对的话就会报错
props:{
    name:String
},
// 3 给个名称不仅指定了类型,还顺便送了个默认值,当父组件传个空过来或者啥都没传过来的时候就用默认值了
props: {
  name: {
    type: String,
    default: 'xhm',
  }
},

注意一下的话,如果是数组或者是对象要默认值的话,直接设置默认数组或者默认对象会报错,需要用工厂函数返回,如下:


props: {
  arr:{
    type:Array,
    default:()=&gt;{
       return [1,2,3]
    }
  }
},
// 对象也是和上面一个用工厂函数

1.2 子组件使用父组件的值

由于单向数据流的限制,我们不能直接在子组件中修改 props 的值,当我们修改的时候会报错,官方的说法是:

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。

额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。

所以啊,如果你不只是想在子组件中简单的渲染父组件传过来的值的话,那么可以用下面的两种方法。

  1. 这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用。在这种情况下,最好定义一个本地的 data 属性并将这个 prop 用作其初始值:

props: ['name'],
data() {
  return {
    userName:this.name,
  };
},
  1. 这个 prop 以一种原始的值传入且需要进行转换。在这种情况下,最好使用这个 prop 的值来定义一个计算属性:

props: ['name'],
computed: {
  userName(){
    return this.firstName + this.name
  }
},

2 子组件传值给父组件

虽然我们说是要单向数据流,但是很多时候,我们在子组件改变了某些值之后,还是要反馈给父组件,让父组件做一下修改,那么这个时候就要想着子组件向父组件传值啦。有下面这么两种方式

2.1 emit 方法

这个基本都是用 emit 来传递了,用法直接看代码吧:
子组件


// props:['name]

// methods 里
update(){
  this.$emit('update','ljy');
  // 第一个参数:事件名,第二个参数:传递给事件方法的参数
}

父组件



/* template 里面的代码,监听子组件里面的 update 事件,调用父组件的 childUpdate 方法

 &lt;child :name="userName" @update="childUpdate"&gt;&lt;/child&gt;

*/
// methods
chidlUpdate(val){
  // val 参数就是子组件传递过来的数据
  this.userName = val;
}

虽然这样是可以实现子组件向父组件传值,但是写多一个方法感觉很烦,所以 vue 官方高出了一个 以 update:myPropName 的模式触发事件。,这个是啥,举个例子,我们的子组件中有一个 name 的 props,我们用下面这个形式通知父组件


this.$emit('update:name', newName)
// this.$emit('update:props中的变量名', 新的值)

然后父组件可以监听那个事件并根据需要更新一个本地的数据属性:

```<child :name="userName" @update:name="userName = $event"></child> ```

这样当我们在子组件触发那个修改的方法的时候,父组件的 userName 变量就会更新为 newName了,然后为了方便起见,官方提供了一个缩写,即 .sync 修饰符。看代码吧:

```<child :name.sync="userName"></child> ```

上面的代码和前面的代码是一个效果,是不是方便了很多。舒服了吧。

2.2 利用浅拷贝(不推荐)

这个的话是针对于 对象和数组那些引用类型的数据而言的,由于这些存在浅拷贝的问题(不明白浅拷贝的看这篇文章),所以可以利用这点来实现子父组件的「同生共死」,看代码吧


// 假设 name 是一个对象或者数组
props:['name'],
return {
  userName:this.name,
};

就这样?!

没错就是这么简单粗暴,由于浅拷贝的问题,我们在子组件修改 userName 的时候,从父组件传递过来的那个值也会改变的,然后就会实现 props 的「双向绑定」了。但是一般没人会这么干,因为这样会造成维护上的问题,会让人觉得咋没干啥父组件的值咋就变了,会让人头秃啊,所以除非你项目中非得要搞这么一个子父组件 props 的「同生共死」,那就这么干吧。

3 子组件调用父组件的方法

不知道这样的叫法对不对,反正就这样啦。总结之后又下面这几种方法

3.1 emit

其实本来 emit 就是用于子组件向父组件通信的,上面的子组件传值给父组件其实也就是父组件监听子组件的事件,然后触发父组件的方法的,换个说法,也就是子组件调用了父组件的方法,再写一下代码吧:

子组件


// methods 里
update(){
  this.$emit('update','ljy');
  // 第一个参数:事件名,第二个参数:传递给事件方法的参数
}

父组件



/* template 里面的代码,监听子组件里面的 update 事件,调用父组件的 childUpdate 方法

 &lt;child :name="userName" @update="childUpdate"&gt;&lt;/child&gt;

*/
// methods
chidlUpdate(val){
  // val 参数就是子组件传递过来的数据
  this.userName = val;
}

上面的代码中,从某种意义上来说,就是子组件调用了父组件的 childUpdate 方法。

3.2 this.$paarent.event

这个就比较简单了,我们假设我们在父组件定义了一个 fatherMethod() 方法,然后我们子组件就可以通过下面的代码实现调用 fatherMethod() 的方法


childClick(){
  this.$parent.fatherMethod();
}

3.3 props

props 能传递 Function 类型的数据,所以,我们通过 props 当然也是可以直接的调用父组件传递过来的方法啦。不多说,直接撸代码:
父组件

```<!-- 假设父组件里定义了一个 fatherMethod() 方法 --> <child :fatherMethod="fatherMethod"></child> ```

子组件


props: {
  fatherMethod: {
    type: Function,
    default: null
  }
},
methods: {
  childClick() {
    this.fatherMethod();
  }
},

这样我们也是调用了父组件的方法啦。

4 父组件调用子组件的方法

这个,暂时没有遇到过这种情况,不过以备不时之需,也写一下吧。父组件调用子组件的方法的话是利用 ref 获取到子组件实例,从而调用子组件的方法,假设我们子组件有这么一个 childMethod() 方法。那么我们的父组件就可以这么来调用子组件的方法了


/* &lt;child ref="con"&gt;&lt;/child&gt; 子组件 */

methods: {
  update() {
    this.$refs.con.childMethod();
  },
}

至此,关于父子组件通信的的话题就聊到这边了,如果有啥错误或者遗漏的,欢迎在下面斧正啦。

原文地址:https://segmentfault.com/a/1190000017346476

相关文章
|
15天前
|
缓存 JavaScript 前端开发
vue学习第四章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中计算属性的基本与复杂使用、setter/getter、与methods的对比及与侦听器的总结。如果你觉得有用,请关注我,将持续更新更多优质内容!🎉🎉🎉
32 1
vue学习第四章
|
15天前
|
JavaScript 前端开发
vue学习第九章(v-model)
欢迎来到我的博客,我是瑞雨溪,一名热爱JavaScript与Vue的大一学生,自学前端2年半,正向全栈进发。此篇介绍v-model在不同表单元素中的应用及修饰符的使用,希望能对你有所帮助。关注我,持续更新中!🎉🎉🎉
27 1
vue学习第九章(v-model)
|
15天前
|
JavaScript 前端开发 开发者
vue学习第十章(组件开发)
欢迎来到瑞雨溪的博客,一名热爱JavaScript与Vue的大一学生。本文深入讲解Vue组件的基本使用、全局与局部组件、父子组件通信及数据传递等内容,适合前端开发者学习参考。持续更新中,期待您的关注!🎉🎉🎉
30 1
vue学习第十章(组件开发)
|
21天前
|
JavaScript 前端开发
如何在 Vue 项目中配置 Tree Shaking?
通过以上针对 Webpack 或 Rollup 的配置方法,就可以在 Vue 项目中有效地启用 Tree Shaking,从而优化项目的打包体积,提高项目的性能和加载速度。在实际配置过程中,需要根据项目的具体情况和需求,对配置进行适当的调整和优化。
|
8天前
|
前端开发 JavaScript 测试技术
Vue3中v-model在处理自定义组件双向数据绑定时,如何避免循环引用?
Web 组件化是一种有效的开发方法,可以提高项目的质量、效率和可维护性。在实际项目中,要结合项目的具体情况,合理应用 Web 组件化的理念和技术,实现项目的成功实施和交付。通过不断地探索和实践,将 Web 组件化的优势充分发挥出来,为前端开发领域的发展做出贡献。
21 8
|
8天前
|
JavaScript
在 Vue 3 中,如何使用 v-model 来处理自定义组件的双向数据绑定?
需要注意的是,在实际开发中,根据具体的业务需求和组件设计,可能需要对上述步骤进行适当的调整和优化,以确保双向数据绑定的正确性和稳定性。同时,深入理解 Vue 3 的响应式机制和组件通信原理,将有助于更好地运用 `v-model` 实现自定义组件的双向数据绑定。
|
21天前
|
存储 缓存 JavaScript
在 Vue 中使用 computed 和 watch 时,性能问题探讨
本文探讨了在 Vue.js 中使用 computed 计算属性和 watch 监听器时可能遇到的性能问题,并提供了优化建议,帮助开发者提高应用性能。
|
21天前
|
存储 缓存 JavaScript
如何在大型 Vue 应用中有效地管理计算属性和侦听器
在大型 Vue 应用中,合理管理计算属性和侦听器是优化性能和维护性的关键。本文介绍了如何通过模块化、状态管理和避免冗余计算等方法,有效提升应用的响应性和可维护性。
|
21天前
|
存储 缓存 JavaScript
Vue 中 computed 和 watch 的差异
Vue 中的 `computed` 和 `watch` 都用于处理数据变化,但使用场景不同。`computed` 用于计算属性,依赖于其他数据自动更新;`watch` 用于监听数据变化,执行异步或复杂操作。
|
20天前
|
JavaScript 前端开发 UED
vue学习第二章
欢迎来到我的博客!我是一名自学了2年半前端的大一学生,熟悉JavaScript与Vue,目前正在向全栈方向发展。如果你从我的博客中有所收获,欢迎关注我,我将持续更新更多优质文章。你的支持是我最大的动力!🎉🎉🎉
27 3