首页>>前端>>Vue->Vue2与Vu3组件通信方式总结

Vue2与Vu3组件通信方式总结

时间:2023-11-29 本站 点击:0

我们都知道Vue作为一个轻量级的低门槛入门前端框架,其核心就是组件化开发。Vue就是由多个组件组建成的,组件化是它的精髓,更是它的强大之处。各组件实例之间是相互独立的,这也就意味着不同组件之间数据是无法相互共用。

但实际项目开发中,我们时常需要其他组件的数据,为此诞生了组件通信的问题。针对组件之前的关系:父子、兄弟、子孙的不同选用的数据传输方式也不一样,今天就来做个总结。

Vue2组件通信

父组件向子组件传值

props

父组件以属性的方式传值给子组件

子组件通过props方式接收数据

在父组件中引入子组件并绑定fatherData自定义属性

<Son:fatherData="fatherData"></Son><script>importSonfrom'@/components/son'exportdefault{name:'Father',components:{Son},data(){return{fatherData:'我是父组件向子组件传递的值-props方式'}}}</script>

在子组件中使用props接收父组件传递的数据,props里的名字跟父组件定义的属性名一致

<template><div>我是父组件的数据:{{fatherData}}</div><div>我是父组件传递修改后的数据:{{mydata}}</div></template><script>exportdefault{name:'Son',props:{fatherData:{type:String,default:''}}data(){mydata:'公众号:初级前端仔'+this.fatherData},watch:{fatherData(newVal){this.mydata='公众号:初级前端仔'+newVal}},}</script>

因为Vue的单向数据流机制,子组件不能够直接去修改父组件传递的值修改的,否则能改的话那父组件的值就被“污染”了。

但是子组件内想要修改父组件传过来的值却不“污染”父组件的话,可以在子组件内定义一个变量mydata去接收fatherData数据,并使用watch监听fatherData数据的变更。

子组件向父组件传值

$emit()

子组件绑定自定义事件

使用$emit()触发更改数据

<el-button@click="handleEmit">告诉父组件我要更改数据啦</el-button><script>exportdefault{name:'Son',methods:{handleEmit(){this.$emit('triggerEmit','我是来自子组件的数据')}}}</script>

父组件定义并绑定子组件传递的triggerEmit事件

triggerEmit事件名需跟子组件$emit()的事件名一致

<Son@triggerEmit="changeData"></Son><script>importSonfrom'@/components/son'exportdefault{name:'Father',components:{Son},methods:{changeData(name){console.log(name)//=>我是来自子组件的数据}}}</script>

使用场景:通用组件更改内部的数据时告知父组件此时数据状态。

兄弟之前传值

$emitprops结合的方式

父组件引入两个子组件

父组件充当一个桥梁作用

<childA:myName="name"></ChildA><ChildB:myName="name"@changeName="editName"></ChildB>exportdefault{data(){return{name:'初级前端仔'}},methods:{editName(name){this.name=name}}}

在子组件B中接收变量和绑定触发事件

<p>姓名:{{myName}}</p><button@click="changeName">修改姓名</button><script>exportdefault{props:{myName:String},methods:{changeName(){this.$emit('changeName','公众号:初级前端仔')}}}</script>

父组件接受到B组件的changeName事件,就会执行editName事件并修改name的数据,利用响应式机制,父组件就会将最新的name值传递给组件A,组件A渲染最新的name值

<p>姓名:{{newName}}</p><script>exportdefault{props:{myName:String}}</script>

至今组件B的更改就通过父组件传达到给组件A完成数据的传递

bus方式

创建一个公共的bus.js文件

暴露出Vue实例

importVuefrom"vue"exportdefaultnewVue()

在需要组件通信的组件中都引入该文件

<template><div><div>我是通信组件A</div><el-button@click="changeName">修改姓名</el-button></div></template<script>import{EventBus}from"../bus.js"exportdefault{data(){return{}},methods:{changeName(){EventBus.$emit("editName",'初级前端仔,点点关注!')}}}</script>

另外一个组件中同样引入bus.js文件,通过$on监听事件回调

<template><div>我是通信组件B</div></template<script>import{EventBus}from"../bus.js"exportdefault{data(){return{}},mounted:{EventBus.$on('editName',(name)=>{console.log(name)//=>初级前端仔,点点关注!})}}</script>

通过引入bus.js文件,使得EventBus获得Vue实例,其实是跟上一种方式是一样的。

直接访问组件实例

parent/children

子组件通过$parent获得父组件实例

父组件通过$children获得子组件实例数组

<template><div>我是父组件的数据:{{fatherData}}</div><div>我是父组件传递修改后的数据:{{mydata}}</div></template><script>exportdefault{name:'Son',props:{fatherData:{type:String,default:''}}data(){mydata:'公众号:初级前端仔'+this.fatherData},watch:{fatherData(newVal){this.mydata='公众号:初级前端仔'+newVal}},}</script>0

由图可知this.$parent可以获取到父组件的方法、data的数据等,并可以直接使用和执行。

<template><div>我是父组件的数据:{{fatherData}}</div><div>我是父组件传递修改后的数据:{{mydata}}</div></template><script>exportdefault{name:'Son',props:{fatherData:{type:String,default:''}}data(){mydata:'公众号:初级前端仔'+this.fatherData},watch:{fatherData(newVal){this.mydata='公众号:初级前端仔'+newVal}},}</script>1

正如你所看到的,父组件是在mounted()生命周期中获取子组件实例的,并且获取的实例是一个数组形式

所以需要this.$children[0]才可以获取某个组件实例,并调用组件方法和数据

$refs

父组件使用$refs获得组件实例

<template><div>我是父组件的数据:{{fatherData}}</div><div>我是父组件传递修改后的数据:{{mydata}}</div></template><script>exportdefault{name:'Son',props:{fatherData:{type:String,default:''}}data(){mydata:'公众号:初级前端仔'+this.fatherData},watch:{fatherData(newVal){this.mydata='公众号:初级前端仔'+newVal}},}</script>2

这样父组件就可以直接使用this.$refs.xx获取子组件的实例了

多组件或深层次组件通信

provide/inject(提供/注入)

父组件使用provide注入数据

子组件使用inject使用数据

例如,如果我们有这样的层次结构:

那么我们的provide/inject就可以派上用场了

<template><div>我是父组件的数据:{{fatherData}}</div><div>我是父组件传递修改后的数据:{{mydata}}</div></template><script>exportdefault{name:'Son',props:{fatherData:{type:String,default:''}}data(){mydata:'公众号:初级前端仔'+this.fatherData},watch:{fatherData(newVal){this.mydata='公众号:初级前端仔'+newVal}},}</script>3

至此provideName这个变量可以提供给它其下的所有子组件,包括曾孙、孙子组件等,只需要使用inject就能获取数据

<template><div>我是父组件的数据:{{fatherData}}</div><div>我是父组件传递修改后的数据:{{mydata}}</div></template><script>exportdefault{name:'Son',props:{fatherData:{type:String,default:''}}data(){mydata:'公众号:初级前端仔'+this.fatherData},watch:{fatherData(newVal){this.mydata='公众号:初级前端仔'+newVal}},}</script>4

这个方法的好处是:

父组件不需要知道哪个组件使用它提供出去的数据

子附件不需要知道这个数据从哪里来

vuex状态管理

相当于一个公共数据的仓库

提供一些方法管理仓库数据

关于这个的话直接去看官网吧 vuex[https://vuex.vuejs.org/zh]


总结

至此vue2中组件通信的方式就总结完了,主要分为三大类:

. 父子通信:父向子传递数据通过props,子向父传递数据通过$emit事件,父链/子链使用parent/children,直接访问组件实例用refs

. 兄弟通信:bus、Vuex

. 跨级通信:bus、Vuex、provide/inject

Vue3组件通信

props和emit

setup函数可以接受两个参数,prop和context,其中context可以解构出emit实例

<template><div>我是父组件的数据:{{fatherData}}</div><div>我是父组件传递修改后的数据:{{mydata}}</div></template><script>exportdefault{name:'Son',props:{fatherData:{type:String,default:''}}data(){mydata:'公众号:初级前端仔'+this.fatherData},watch:{fatherData(newVal){this.mydata='公众号:初级前端仔'+newVal}},}</script>5

Vue3中没有this的概念了,所以就不会有this.$emit存在,所以可以从setup传入的context结构出emit实例,从而派发事件给父组件

<template><div>我是父组件的数据:{{fatherData}}</div><div>我是父组件传递修改后的数据:{{mydata}}</div></template><script>exportdefault{name:'Son',props:{fatherData:{type:String,default:''}}data(){mydata:'公众号:初级前端仔'+this.fatherData},watch:{fatherData(newVal){this.mydata='公众号:初级前端仔'+newVal}},}</script>6

ref

Vue3我们可以从Vue中导出ref方法,得到子组件的实例

<template><div>我是父组件的数据:{{fatherData}}</div><div>我是父组件传递修改后的数据:{{mydata}}</div></template><script>exportdefault{name:'Son',props:{fatherData:{type:String,default:''}}data(){mydata:'公众号:初级前端仔'+this.fatherData},watch:{fatherData(newVal){this.mydata='公众号:初级前端仔'+newVal}},}</script>7

通过,在子组件声明ref属性,属性值必须和const btnRef = ref(null)这里声明的变量名一致,否则会报错,拿到子组件实例后就可以直接调用组件的sendParent方法了

这里使用的btnRef.value?.是可选链操作符语法,代表?前面的值为true才继续执行后面的语句,感兴趣的小伙伴可以点击去看看,这里就不赘叙了

<template><div>我是父组件的数据:{{fatherData}}</div><div>我是父组件传递修改后的数据:{{mydata}}</div></template><script>exportdefault{name:'Son',props:{fatherData:{type:String,default:''}}data(){mydata:'公众号:初级前端仔'+this.fatherData},watch:{fatherData(newVal){this.mydata='公众号:初级前端仔'+newVal}},}</script>8

子组件只提供一个方法,供父组件获取实例后执行,也可以执行更为复杂的数据通信

provide/inject

这里的用法跟Vue2差异不大,直接上案例吧

<template><div>我是父组件的数据:{{fatherData}}</div><div>我是父组件传递修改后的数据:{{mydata}}</div></template><script>exportdefault{name:'Son',props:{fatherData:{type:String,default:''}}data(){mydata:'公众号:初级前端仔'+this.fatherData},watch:{fatherData(newVal){this.mydata='公众号:初级前端仔'+newVal}},}</script>9

直接使用provide将需要传递的数据注入,不需要考虑谁去获取

<el-button@click="handleEmit">告诉父组件我要更改数据啦</el-button><script>exportdefault{name:'Son',methods:{handleEmit(){this.$emit('triggerEmit','我是来自子组件的数据')}}}</script>0

子孙组件使用inject获取到父组件注入的数据

感谢


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/Vue/829.html