前言
之前写过一篇关于vue采访总结的文章,很多网友建议组件之间还是有很多沟通方式的。本文具体总结了组件之间的通信
Vue是一个数据驱动的视图更新框架,因此组件之间的数据通信对于vue来说非常重要。组件如何相互通信?首先,我们需要知道vue中的组件之间存在什么样的关系,这样更容易理解它们的通信方式。就像回家过年,坐在满是陌生人的房间里,互相呼唤。这个时候,我们需要知道我们和他们是什么样的关系。
vue组件:中的关系描述
如上图所示,A和B,A和C,B和D,C和E组件是父子关系;b和C是兄弟;A与D、A与E之间存在代际关系;d和E是表亲(不是直系亲属)
根据上述关系,我们将其分类为:
父子组件之间的通信不是父子组件(兄弟组件、代际组件等)之间的通信。).本文将介绍如下图(:)所示的8种组件间的通信方式,并介绍如何在不同场景下选择有效的方式实现组件间的通信,希望能帮助朋友们更好的理解组件间的通信。
一、道具/$emit
父组件通过道具将数据传输给子组件,而子组件可以通过$emit与父组件通信。
1.父组件将值传递给子组件
这里有一个例子来说明父组件如何将数据传输给子组件:如何获取父组件部分的数据
//section父组件模板div class=' section ' com-article : articles=' article list '/com-article/div/templatescriptort com article from '。/测试/文章。vue ' export default { name : ' hello world ',components : {article},data(){ return { article list :[《红楼梦》,《西游记》,《三国演义》]} }/script//subcomponent article . vue template div span v-for='(item,Index)in articles ' : key=' Index ' { item } }/span/templatescript exportdefault { prop 3360[' articles ']}/script summary 33:此外,prop是只读的,不能修改。所有修改都将无效并被警告。
2.子组件将该值传递给父组件
我自己对$emit的理解是: $emit绑定了一个自定义事件。执行此语句时,参数arg将被传递给父组件,父组件将通过v-on侦听并接收参数。给出了一个例子来说明子组件如何将数据传输到父组件。
在前面示例的基础上,单击页面上呈现的数组项,下标显示在父组件的数组中
//template div class=' section ' com-article : articles=' article list ' @ onemitindex=' onemitindex '/com-article p { { current index } }/p/div/templatescript import comArticle from '。/test/article . vue ' export default { name : ' hello world ',components: { comArticle },Data(){ return { current index :-1,article list : [《红楼梦》,《西游记》,《三国演义》]} } } } },Methods : { onEmitIndex(idx){ this . currentindex=idx } }/script template div-for='(item,index)in articles ' 33333330$ emit ('onemitindex ',index)}}}/script II,$children/$parent
上图是vue的官方解释。您可以通过$parent和$ children访问组件的实例,并获取该实例所表示的内容。表示可以访问此组件的所有方法和数据。下一步是如何获取指定组件的实例。
施用方式
//template div class=' hello _ world ' div { { msg } }/div com-a/com-a button @ click=' changea '在父组件中,单击可更改子组件/button/div/templatescriptimport coma from '的值。/test/CoMa . vue ' export default { name : ' hello world ',components: { ComA },data(){ return { msg : ' Welcome ' } },Methods: {changeA() {//获取了子组件a this。$ children [0]。messagea='这是新值' }} } }/script//template div class=' com _ a ' Span { { message a } }/Span p获取父组件的值为: { { parent val } }/p/div/template scriptexportdefault { data(){ return { message a : '这是旧的' } },computed : { parent val(){ return this。$ parent.msg} } }/脚本要注意边界条件。例如,如果在#app上取$parent,就会得到一个new Vue()的实例,如果在这个实例上取$parent,就会得到undefined,如果在底层子组件上取$children,就会得到一个空数组。还要注意$parent和$ children的值是不同的。$children的值是一个数组,而$parent是一个对象
总结以上两种方式用于父子组件之间的通信,使用道具进行父子组件之间的通信比较常见;两者都不能用于非父组件和子组件之间的通信。
第三,提供/注入
概念:
Provide/inject是vue2.2.0中新增的api,简单来说就是父组件通过Provide提供变量,然后子组件通过inject注入变量。
注意这里的:不管子组件嵌套有多深,只要调用inject,provide中的数据都可以被注入,并不局限于只从当前父组件的props属性返回数据
示例验证
接下来,用一个例子来验证上述描述:
假设有三个组件: A.vue、B.vue和C.vue,其中c是b的子组件,b是a的子组件。
//a . vuetemplate DivcomB/ComB/div/template script从导入ComB './components/test/ComB . vue ' export default { name : ' A ',provide: { for: 'demo' },components 3360 { ComB } }/script//b . vuetemplate div { { demo } } ComC/ComC/div/template script import ComC from './Components/test/ComC . vue ' export default { name : ' B ',inject: ['for'],data() { return { demo: this . for } },Components : { ComC } }/script//c . vue template div { { demo } }/div/template script export default { name : ' c ',inject : ['for'],data(){ return { demo : this。for}}}/。
引用:如果在普通的DOM元素上使用,引用指向DOM元素;如果在子组件上使用,则引用指向组件实例,您可以直接调用组件的方法或通过实例访问数据。让我们看一下访问组件示例:的引用
//子组件a. vue导出默认值{ data(){ return { name : ' vue . js ' } },methods : { say hello(){ console . log(' hello ')}//父组件app.vue模板组件-a ref=' coma '/组件-a/模板脚本导出默认值{mounted () {const coma=this。$ refs.com;console . log(CoMa . name);//Vue . js CoMa . SayHello();//hello} }/script v. eventBus
EventBus也称为事件总线,可以作为vue中通信桥的概念,就像所有组件共享同一个事件中心一样,并且可以注册发送或接收事件,因此组件可以通知其他组件。
EventBus也有一些不便之处。当项目规模较大时,容易造成难以维护的灾难
Vue项目中如何使用eventBus实现组件间的数据通信?具体通过以下步骤
1.初始化
首先,我们需要创建一个事件总线并导出它,以便其他模块可以使用它或收听它。
//event-bus.js从' vue '导入vue,导出const event bus=newvue () 2。发送事件
假设你有两个组件, additionNum和showNum,可以是兄弟组件,也可以是父子组件;这里我们以兄弟组件为例:
模板div show-num-com/show-num-com addition-num-com/addition-num-com/div/templatescriptimport showNumCom from '。/showNum.vue“从OutLook导入附加组件”。/additionnum . vue ' export default { components 3360 { showNumCom,Additionnumcom } }/script//additionnum . vue send event template div button @ click=' additiononhandle ' add/button/div/template script import { event bus from }。/Event-bus . js ' console . log(Event bus)导出默认值{data () {return {num:1}},methods : { additionhandle(){ Event bus。$ emit('加法',{num3360this.num})}}/script3
//showNum.vue从“”接收事件模板div计算和: { { count } }/div/templatescriptimport { event bus }。/event-bus . js ' export default { data(){ return { count : 0 } },mounted() { EventBus。$on('加法',param={ this . count=this . count param . num;})} }/脚本这样,点击组件addtionNum.vue中的add按钮,在showNum.vue中显示求和结果.
4.删除事件侦听器
如果您想取消对事件的监控,您可以按如下方式操作:
从“event-bus.js”事件总线导入{event bus}。$ off('加法',{}) VI。状态管理
1.vuex简介
Vuex是专门为Vue.js应用开发的状态管理模式。它使用集中式存储来管理应用程序所有组件的状态,并确保状态以可预测的方式根据相应的规则进行更改。
Vuex解决了多个视图依赖同一个状态,来自不同视图的行为需要改变同一个状态的问题,将开发人员的精力集中在更新数据上,而不是在组件之间传递数据
2.Vuex的每个模块
状态:用于数据存储,是存储中唯一的数据源。getters:与vue中的计算属性一样,基于状态数据的二次封装,常用于多数据的数据过滤和相关性计算。变体:类似的突变,改变状态数据的唯一方法,不能用于处理异步事件。actions:类似于variation,用于提交突变来改变状态,而不直接改变状态。它可以包含任何异步操作模块:类似于namespace,用于在项目中单独定义和操作每个模块的状态,便于维护。3.Vuex实例应用程序
//父组件模板div id=' app '子a/child b//div/模板脚本从导入子a '。/components/child a '/import a component import child b from '。/components/child b '/import bcomponent export default { name : ' app ',components: { child a,child b }//register a and b components }/script//subcomponent child a template div id=' child a ' h1I是一个组件/h1 button @click='transform '点我让b component接收数据/button p因为你点了b,所以我的信息发生了变化:{ { bmessage } }/p/div/template script export default { data(){ return { a message 3: ' hello,b componentComputed: {BMessage() {//这里,存储从store获取的b组件的数据,返回这个。$ store.state.bmsg}},methods : { transform(){//trigger receiveAMsg。将组件A的数据存储在存储中。$ store.submit ('receiveamsg ',{amsg:this。a message })} } }/script//subcomponent child template div id=' child b ' h1I是b组件/h1 button @click='transform '点,我让a组件接收数据/button p因为你点了a,所以,我的信息发生了变化:{ { a message } }/p/div/template script导出默认{ data(){ return { b message : ' hello,a component,我是b component'}}。Computed: {AMessage() {//这里,存储从store获取的A组件的数据,返回这个。$ store.state.amsg}},methods : { transform(){//trigger receiveBMsg。将组件B的数据存储在存储中。这个。$ store.submit ('receivebmsg ',{bmsg:this。bmessage})}}/scriptvuex的商店,js
从“vue”导入vue从“vuex”导入vuex。使用(vuex)const state={//初始化组件a和b的数据,等待获取AMsg: ' '。Bmsg: ' ' } const variations={接收amsg (state,Payload) {//将组件a的数据存储在statestate.amsg=payload.amsg}中,接收bmsg (state,Payload){//将组件b的数据存储在state.bmsg=payload.bmsg}中}导出默认的newvuex.store ({state,variants })VII。本地存储/会话存储
这种通信相对简单,但缺点是数据和状态混乱,难以维护。
通过window . local storage . getitem(key)获取数据
通过window.localstorage.setitem保存数据(键,值)
注意使用JSON。parse ()/JSON。stringfy()用于数据格式转换。localStorage/sessionStorage可以与vuex结合实现数据持久化,同时可以利用vuex解决数据和状态混淆的问题。
八个$ attrs和$ listeners
现在,让我们讨论一个情况。在我们一开始给出的成分关系图中,A成分和D成分是代际的。他们以前有哪些沟通方式?
使用道具绑定逐级传递信息。如果d组件中的状态变化需要将数据传输到a,则使用eventBus逐级传输。在这种情况下,更适合使用它。然而,当多人合作开发时,代码维护性低,可读性低。Vuex用于数据管理。然而,如果它只传输数据而不进行中间处理,那么使用Vuex就有点矫枉过正了。在vue2.4中,为了解决这个需求,引入了$ attrs和$ listeners,并增加了inheritAttrs选项。在2.4版本之前,默认情况下,在父范围内不被识别(和获取)为prop的属性绑定(类和样式除外)将被“回滚”,并作为普通HTML属性应用于子组件的根元素。接下来,看一个跨级别通信:的例子
//app.vue//index。vuetemplate div child-com 1 : name=' name ' 3360 age=' age ' : gender=' gender ' : height=' height ' title='程序员向北生长'/child-com 1/div/templatescript child com 1=()=import('。/child com 1 . vue ');导出默认{组件: {childcom1},数据(){返回{姓名: '张',年龄:' 18 ',性别: '女',身高: ' 158 ' };}};/script//childcom1.vuetemplate类=' border ' div pname 3360 { { name } }/$ attrs : { { $ attrs } } of pchildcom 1/pchildcom 2v-bind=' $ attrs '/child-com 2/div/templatescriptcostconst childcom 2=()=import('。/child com 2 . vue’);export default { components : { child com 2 },inheritattrs: false。//可以关闭props : { name 3360 string//name这种没有在props中声明的属性,自动挂载到组件根元素上,并将其绑定为props属性},created () {console.log (this。$ attrs//{ '年龄' :' 18 ','性别' : '女','身高' : '158 ','职称' : '程序员的成长指北' } } };/script//childcom 2 . vuetemplate div class=' border ' page : { { age } }/p pchildcom 2: { { $ attrs } }/p/div/templatescriptexport default { inheritarts : false,props: { age: String },created() { console.log(this。$ attrs//{ '性别' : '女','身高' : '158 ','职称' : '程序员的成长指北' } } };/脚本摘要
常见的使用场景可以分为三类:
亲子组件交流:道具;$家长/$孩子;提供/注入;ref$attrs/$listeners兄弟组件通信: eventBusVuex跨级通信: eventBus;Vuex提供/注入$attrs/$listeners好了,这就是本文的全部内容。希望本文的内容对大家的学习或工作有一定的参考价值。谢谢你的支持。