前端面試 vue 部分 (5)——VUE元件之間通訊的方式有哪些

dd多了個多發表於2020-08-06

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查詢命名子元件( )( 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'], 

歡迎留言~~~

相關文章