1. 前言
vue也是组件化开发框架,对于这种组件化开发来说,组件之间的通信方式通常都是非常重要的
所以单独开一个篇章来总结下有哪些通信方式
2. 首先列出常用的组件通信方式
1.props
2.$emit/$on
3.$children/$parent
4.$attrs / $listeners
5.ref
6.$root
7.eventBus
8.vuex
列出来后,可以自己先考虑下应用场景
下面不饶弯子了,以组件的关系来解说通信方式
3. 父子组件通信
3.1 props 父传子
1.父组件以属性的方式传值给子组件
2.子组件通过props方式接收数据
3.1.1父组件核心代码
在父组件中引入子组件并绑定parentData自定义属性
<Child:parentData="parentData"></Child > <script> import Child from '@/components/child' export default{ name:'Parent', components:{Child}, data(){ return{ parentData:'我是父组件向子组件传递的值-props方式' } } } </script>
3.1.2 子组件核心代码
1.在子组件中使用 props 接收父组件传递的数据,
2.props 里的名字跟父组件定义的属性名一致
<template> <div>我是父组件的数据:{{parentData}}</div> <div>我是父组件传递修改后的数据:{{mydata}}</div> </template> <script> export default{ name:'Child', props:{ parentData:{ type:String, default:'' } } data(){ mydata:'俺的小破站 '+ this.parentData }, watch:{ parentData(newVal){ this.mydata='俺的小破站 '+ newVal } }, } </script>
Vue的
单向数据流
机制,子组件不能
够直接去修改父
组件传递的值
修改的,否则能改的话那父组件的值就被污染
了。但是子组件内想要修改父组件传过来的值却不“污染”父组件的话,
可以在子组件内定义一个变量mydata去接收parentData数据,并使用 watch 监听parentData数据的变更
3.2 $emit/$on 子传父
1.子组件绑定自定义事件
2.使用 $emit() 触发更改数据
3.2.1 子组件核心代码
<el-button @click="handleEmit">告诉父组件我要更改数据啦</el-button> <script> export default{ name:'Child', methods:{ handleEmit(){ this.$emit('triggerEmit','我是来自子组件的数据') } } } </script>
3.2.2父组件核心代码
1.父组件定义并绑定子组件传递的triggerEmit事件
2.triggerEmit事件名需跟子组件 $emit() 的事件名
<Child @triggerEmit="changeData"></Child> <script> import Child from '@/components/child' export default{ name:'Parent', components:{Child}, methods:{ changeData(name){ console.log(name) // => 我是来自子组件的数据 } } } </script>
3.3 $parent/$children
1.子组件通过 $parent 获得父组件实例
2.父组件通过 $children 获得子组件实例数组
3.3.1 子组件
<template> <div>我是子组件</div> </template> <script> export default{ name:"Child", data(){ return{ childTitle: '我是子组件的数据' } }, methods:{ childHandle(){ console.log('我是子组件的方法') } }, created(){ console.log(this.$parent) console.log(this.$parent.parentTitle) // => 我是父组件的数据 this.$parent.parentHandle() // => 我是父组件的方法 } } </script>
this.$parent可以获取到父组件的方法、data的数据等,并可以直接使用和执行。
3.3.2 父组件
<template> <div> <Child>我是父组件</Child> </div> </template> <script> import Child from './child.vue' export default{ name: 'parent', components:{ Child }, data(){ return{ parentTitle: '我是父组件的数据' } }, methods:{ parentHandle(){ console.log('我是父组件的方法') } }, mounted(){ console.log(this.$children) console.log(this.$children[0].childTitle) // => 我是子组件的数据 this.$children[0].childHandle() // => 我是子组件的方法 } } </script>
3.3.3 注意钩子的使用
父组件是在
mounted()
生命周期中获取子组件实例的,并且获取的实例是一个数组形式
3.3.4 问题 层级发生变化的时候咋办呢 ???
1.源码其实有更高层次的封装,在引用
parent
到时候抽象一个更高级的方法类似dispatch
,2.直接
指定
比较重要的父组件的类型
或者名称
,在循环查找的时候避免程序的脆弱性
3.4 ref
父组件使用 $refs 获得组件实例
<template> <div> <Child ref="child"></Child > </div> </template> <script> import Child from './child.vue' export default{ name: 'parent', components:{ Child }, mounted(){ console.log(this.$refs.child ) /*组件实例*/ } } </script>
1.注意 钩子
mounted
- 父组件就可以直接使用this.$refs.xx获取子组件的实例
3.5 $attrs/$listeners
4. 兄弟组件
核心就是找共同点, 搭建桥梁,中间人,话事人的感觉
4.1 $parent
既然是兄弟往上找 总能找到共同的祖先
不常用,可以参考文章上面 的 写法
4.2 $root
其实 根也是共享的
4.3 eventBus 也是都可以访问的
4.3.1 创建一个Vue实例
作为调度中心 eventBus
import Vue from "vue" export default new Vue()
4.3.2 需要进行通信的组件中 引入
<template> <div> <div>我是通信组件A</div> <el-button @click="changeName">修改</el-button> </div> </template <script> import { EventBus } from "../bus.js" export default{ data(){ return{} }, methods:{ changeName(){ EventBus.$emit("editName", '俺的小破站') } } } </script>
4.3.3 监听事件
<template> <div>我是通信组件B</div> </template <script> import { EventBus } from "../bus.js" export default{ data(){ return{} }, mounted:{ EventBus.$on('editName',(name)=>{ console.log(name) // 俺的小破站! }) } } </script>
4.4 vuex
具体可以看我之前写的vuex-0系列
5. 跨级组件
5.1eventBus
5.2 vuex
1.相当于一个公共数据的仓库
2.提供一些方法管理仓库数据
3.具体可以看我之前写的vuex-0系列
5.3.provide/inject
5.3.1 简介
父组件使用 provide 注入数据
子组件使用 inject 使用数据
5.3.2 父组件
export default{ provide: { return{ provideName: '俺的小破站' } } }
5.3.3 分析
provideName
这个变量可以提供
给它其下的所有子组件
,包括曾孙、孙子组件等,只需要使用 inject 就能获取数据
5.3.4 子组件
export default{ inject: ['provideName'], created () { console.log(this.provideName) // 俺的小破站 } }
5.3.5 优缺点
1.父组件不需要知道哪个组件使用它提供出去的数据
2.子组件不需要知道这个数据从哪里来
3.更加的原生,不会对第三方库产生依赖
缺点:单向的;只能祖辈向子辈传值