前端面试 vue 部分 (5)——VUE组件之间通信的方式有哪些

file

VUE组件之间通信的方式有哪些(SSS)

图片

常见使用场景可以分为三类:

  • 父子通信:

    • null
      父向子传递数据是通过 props ,子向父是通过 $emit / $on
    • $emit / $bus
    • Vuex
    • 通过父链 / 子链也可以通信( $parent / $children
    • ref 也可以访问组件实例
  • 兄弟通信:

    • $emit / $bus
    • Vuex
  • 跨级通信:

    • $emit / $bus
    • Vuex
    • provide / inject API
    • $attrs/$listeners

emit /bus

// main.js 
Vue.prototype.$bus = new Vue() // event Bus 用于无关系组件间的通信。 

A触发B

 //  A 
 this.$bus.$emit('new-messsage-at-me', { 
    data: { conversationID: message.conversationID } 
  }) 
          
//  B 
  mounted() { 
    this.$bus.$on('new-messsage-at-me', event => { 
      if ( 
        event.data.conversationID === this.conversation.conversationID && 
        this.conversation.conversationID !== 
          this.currentConversation.conversationID 
      ) { 
        this.hasMessageAtMe = true 
      } 
    }) 
  }, 

父子组件通信

  1. 父组件向子组件传值( props ):
//App.vue父组件 
<template> 
  <div id="app"> 
    <users v-bind:users="users"></users>//前者自定义名称便于子组件调用,后者要传递数据名 
  </div> 
</template> 
<script> 
import Users from "./components/Users" 
export default { 
  name: 'App', 
  data(){ 
    return{ 
      users:["Henry","Bucky","Emily"] 
    } 
  }, 
  components:{ 
    "users":Users 
  } 
} 
//users子组件  
// 注:组件中的数据共有三种形式:data、props、computed 
<template> 
  <div class="hello"> 
    <ul> 
      <li v-for="user in users">{{user}}</li>//遍历传递过来的值,然后呈现到页面 
    </ul> 
  </div> 
</template> 
<script> 
export default { 
  name: 'HelloWorld', 
  props:{ 
    users:{           //这个就是父组件中子标签自定义名字 
      type:Array, 
      required:true 
    } 
  } 
} 
</script> 
  1. 子组件向父组件传值(B 组件中 $emit, A 组件中 v-on ):
// 子组件 
<template> 
  <header> 
    <h1 @click="changeTitle">{{title}}</h1>//绑定一个点击事件 
  </header> 
</template> 
<script> 
export default { 
  name: 'app-header', 
  data() { 
    return { 
      title:"Vue.js Demo" 
    } 
  }, 
  methods:{ 
    changeTitle() { 
      this.$emit("titleChanged","子向父组件传值");//自定义事件  传递值“子向父组件传值” 
    } 
  } 
} 
</script> 
// 父组件 
<template> 
  <div id="app"> 
    <app-header v-on:titleChanged="updateTitle" ></app-header>//与子组件titleChanged自定义事件保持一致 
   // updateTitle($event)接受传递过来的文字 
    <h2>{{title}}</h2> 
  </div> 
</template> 
<script> 
import Header from "./components/Header" 
export default { 
  name: 'App', 
  data(){ 
    return{ 
      title:"传递的是一个值" 
    } 
  }, 
  methods:{ 
    updateTitle(e){   //声明这个函数 
      this.title = e; 
    } 
  }, 
  components:{ 
   "app-header":Header, 
  } 
} 
</script> 

ref 与parent $children

  • 使用 this.$parent查找当前组件的父组件。
  • 使用 this.children查找当前组件的直接子组件,可以遍历全部子组件, 需要注意children 并不保证顺序,也不是响应式的。
  • 使用 this.root查找根组件,并可以配合children遍历全部组件。
  • 使用 this.refs查找命名子组件( <firstchild ref="one"></firstchild> )( this.refs.one )

attrs /listeners

  • 两者的出现使得组件之间跨组件的通信在不依赖 vuex 和事件总线的情况下变得简洁,业务清晰。
  • A->B->C 多级组件嵌套需要传递数据时,通常使用的方法是通过vuex。如果仅仅是传递数据,而不做中间处理,使用 vuex 处理,未免有点杀鸡用牛刀。Vue 2.4 版本提供了另一种方法,使用 v-bind=”$attrs”, 将父组件中不被认为 props特性绑定的属性传入子组件中,通常配合 interitAttrs 选项一起使用。
  • 简单来说:attrs 与listeners 是两个「对象」,attrs 里存放的是父组件中绑定的非 Props 属性, 唯一缺点 没在props定义的属性 会显示在生成的html标签上, 解决办法:通过inheritAttrs:false,避免顶层容器继承属性;listeners里存放的是父组件中绑定的非原生事件。

A父组件

<template> 
 <div> 
   <child-dom 
    :foo="foo" 
    :coo="coo" 
     v-on:upRocket="reciveRocket" 
   > 
   </child-dom> 
 </div> 
</template> 
<script> 
 import childDom from "@/components/ChildDom.vue"; 
 export default { 
   name:'demoNo', 
   data() { 
     return { 
       foo:"Hello, world", 
        coo:"Hello,rui" 
    } 
  }, 
 components:{childDom}, 
 methods:{ 
   reciveRocket(){ 
      console.log("reciveRocket success") 
   } 
 } 
} 
</script> 

B子组件

<template> 
   <div> 
     <p>foo:{{foo}}</p> 
     <p>attrs:{{$attrs}}</p> 
     <childDomChild v-bind="$attrs" v-on="$listeners"></childDomChild> 
   </div> 
</template> 
<script> 
import childDomChild from './childDomChild'; 
export default { 
   name:'child-dom' 
   props:["foo"], 
   inheritAttrs:false, 
} 
</script> 

C子组件的子组件

<template>  
   <div> 
       <p>coo:{{coo}}</p> 
       <button @click="startUpRocket">我要发射火箭</button> 
   </div> 
</template> 
<script> 
 export default { 
   name:'childDomChild', 
   props:['coo'], 
   methods:{ 
     startUpRocket(){ 
       this.$emit("upRocket"); 
       console.log("startUpRocket") 
     } 
   } 
 } 
</script> 

provide / inject

  • 适用于 隔代组件通信 祖先组件中通过 provider 来提供变量,然后在子孙组件中通过 inject 来注入变量。 provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。
  • 如果是单一的只是拿数据使用,在父组件定义,则在所有子组件都能为之所用
  • 官网不建议在应用中直接使用该办法,理由很直接:他怕你"管不好"

1.一般情况使用都是在app.vue配置为:

provide () { 
  return { 
    isTest: this 
  } 
}, 

2.所有子组件都可以引用 拿到app.vue里面的所有数据

 inject: ['isTest'], 

欢迎留言~~~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335

推荐阅读更多精彩内容