Vue如何在不同场景下实现组件间的数据交流?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。
父子组件间的数据交流
父子组件间的数据交流可分为两种:
1.父组件传递数据给子组件
2.子组件传递数据给父组件
父组件传递数据给子组件——props
这是组件数据沟通中最常见的场景:你让父组件掌握了数据源,然后传递给子组件,供子组件使用
许多人会说,这很简单!用props嘛! 对,正因如此,它不是我要讲的主要内容,不过我们还是用代码简单过一遍:
父组件
<template> <divid="father"> {{'我是父组件'}} <son:text="text"></son> </div> </template> <script> importsonfrom'./son.vue' exportdefault{ data:function(){ return{ text:'从父组件传来的数据' } }, components:{ son:son } } </script> <stylescoped> </style>
子组件:
<template> <div> {{'我是子组件,我接收了'+text}} </div> </template> <script> exportdefault{ props:{ text:{type:String,default:''} } } </script> <!--Add"scoped"attributetolimitCSStothiscomponentonly--> <stylescoped> </style>
demo:
在这个demo里面,我们把“从父组件传来的数据”这一个字符串通过props传递给了子组件
如果我们希望在子组件中改变父组件的数据的话,可以在父组件中定义一个能改变父组件数据的函数,然后通过props将该函数传递给子组件,并在子组件在适当时机调用该函数——从而起到在子组件中改变父组件数据的效果
子组件传递数据给父组件
子组件传递数据给父组件 方式一:回调传参
父组件:
<template> <divid="father"> {{'我是父组件,名称是'+componentName}} <son:changeComponentName="changeComponentName"></son> </div> </template> <script> importsonfrom'./son.vue' exportdefault{ data:function(){ return{ componentName:'组件A' } }, methods:{ changeComponentName:function(newComponentName){ this.componentName=newComponentName } }, components:{ son:son } } </script> <stylescoped> #fatherdiv{ padding:10px; margin:10px; border:1pxsolidgray; } </style>
子组件:
<template> <div> <p>我是子组件:一个button</p> <button@click="()=>changeComponentName(newComponentName)"> 把父组件的名称修改为:彭湖湾的组件 </button> </div> </template> <script> exportdefault{ data:function(){ return{ newComponentName:'彭湖湾的组件' } }, props:{ changeComponentName:{ type:Function, default:()=>{} } } } </script> <!--Add"scoped"attributetolimitCSStothiscomponentonly--> <stylescoped> </style>
demo:
点击前:
点击后:
图解:
点击子组件(按钮)的时候,将父组件的名称从“A”修改为“彭湖湾的组件”
我们从父组件向子组件传递了一个函数(changeComponentName)。并在子组件调用这个函数的时候,以参数的形式传递了一个子组件内部的数据(newComponentName)给这个函数,这样,在父组件中定义的函数(changeComponentName)就可以取得子组件传来的参数了
【PS】 命名太长不好意思
子组件传递数据给父组件 方式二:自定义事件
父组件:
<template> <divid="father"> <div> {{'我是父组件,我的名称是:'+fatherComponentName}} <sonv-on:changeComponentName="changeComponentName"></son> </div> </div> </template> <script> importsonfrom'./son.vue' exportdefault{ data:function(){ return{ fatherComponentName:'A组件' } }, methods:{ changeComponentName:function(componentName){ this.fatherComponentName=componentName } }, components:{ son:son } } </script> <stylescoped> #fatherdiv{ padding:10px; margin:10px; border:1pxsolidgrey; } </style>
子组件:
<template> <div> <p>我是子组件:一个按钮</p> <button@click="clickCallback"> 修改父组件的名称为:彭湖湾的组件 </button> </div> </template> <script> exportdefault{ data:function(){ return{ fatherComponentName:'彭湖湾的组件' } }, methods:{ clickCallback:function(){ this.$emit('changeComponentName',this.fatherComponentName) } } } </script> <!--Add"scoped"attributetolimitCSStothiscomponentonly--> <stylescoped> </style>
demo:
点击前:
点击后:
图解:
通过$emit(event, [...参数]),所有的参数将被传递给监听器回调,也就是我们在父组件中定义的changeComponentName方法,从而实现从子组件中给父组件传参
兄弟组件间的数据交流(有共同父组件的兄弟组件)
父组件:
<template> <divid="father"> <div> {{'我是父组件:father'}} <eldest-son:text="text"></eldest-son> <youngest-son:changeText="changeText"></youngest-son> </div> </div> </template> <script> importeldestSonfrom'./eldestSon.vue' importyoungestSonfrom'./youngestSon.vue' exportdefault{ data:function(){ return{ text:'我是一行文本' } }, methods:{ changeText:function(){ this.text='我是经过改动的一行文本' } }, components:{ eldestSon:eldestSon, youngestSon:youngestSon } } </script> <style> #fatherdiv{ border:1pxsolidgrey; padding:10px; margin:10px; } </style>
兄弟组件1:
<template> <div> <p>我是兄弟组件:eldestSon</p> <p>我有一个可变数据text:{{text}}</p> </div> </template> <script> exportdefault{ props:{ text:{ type:String, default:'' } } } </script> <!--Add"scoped"attributetolimitCSStothiscomponentonly--> <stylescoped> </style>
兄弟组件2:
<template> <div> <p>我是兄弟组件:youngestSon</p> <button@click="changeText">更改eldestSon兄弟组件中的文本</button> </div> </template> <script> exportdefault{ props:{ changeText:{ type:Function, default:()=>{} } } } </script> <!--Add"scoped"attributetolimitCSStothiscomponentonly--> <stylescoped> </style>
点击前:
点击后:
图解:
如果两个兄弟组件间存在这种数据关系的话,我们可以尝试寻找其共同的父组件,使数据和相关方法“提升”到父组件内部,并向下传给两个子组件
这样,其中一个子组件取得了数据,另外一个子组件取得了改变数据的方法,便可以实现上述的数据沟通
【注意】这种场景存在局限性,它要求两个组件有共同父组件。对于这种场景之外的处理方法,请看下文
全局组件间的数据交流——Vuex
我上述的许多场景里面,都运用到了props或者函数传参的方式去处理组件间的数据沟通。然而在稍大型的应用里面,它们都不约而同地给我们带来了很大的麻烦
例如:
1.通过props从父组件向子组件传递数据
对于直接的父子关系的组件,数据流显得很简洁明确,但在大型应用里面,我们上下嵌套许多个组件的时候,这就会导致我们的代码非常地繁琐,并难以维护
2.对于没有共同的父组件的兄弟组件,函数传参的数据传递方式也无能为力了,Vue文档里介绍到,你可以通过以$emit和$on函数为基础的“事件总线”沟通数据,但它无法应对更加大型的应用
这个时候Vuex就成为了实现全局组件间数据交流的最佳方案了
Vuex拥有一个包含全部顶层状态的单一数据源(state)
1.所有的组件都可以使用这个单一数据源里面的数据
2.所有的组件都可以通过派发 动作(actions)修改这个单一数据源里的数据
原本要“走很多弯路”才能实现沟通的数据流,一下子就找到了最短的捷径
实现View层的数据和model层的解耦
在1,2小节中处理的数据(Vue)和第三小节中处理的数据(Vuex),在很多时候是两种不同类型的数据,前者是属于View层,仅负责单纯的UI展示,而model层的大多是从后端取得后注入的数据。
一点建议:
1.Vue部分的代码负责构建View层
2.Vuex部分的代码负责构建model层
(上述的Vue指的是Vuex之外的框架体系)
以上述两点为基础,决定某部分的代码到底要写进Vue里面还是写进Vuex里面,并尽量将两者分开,从而实现View层和model层的解耦,提高前端代码的可维护性和扩展性
看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注恰卡编程网行业资讯频道,感谢您对恰卡编程网的支持。
相关文章
本站已关闭游客评论,请登录或者注册后再评论吧~