1. 程式人生 > 程式設計 >超詳細的vue元件間通訊總結

超詳細的vue元件間通訊總結

目錄
  • 前言
  • 一、props、$emit單向資料流
  • 二、$parent、$children
  • 三、$attrs、$listeners
  • 四、provide、inject
  • 五、eventBus(事件匯流排)
  • 六、x
  • 七、localstorage
  • 總結

前言

元件通訊在我們平時開發過程中,特別是在vue和在react中,有著舉足輕重的地位。本篇將總結在vue中,元件之間通訊的幾種方式:

  • props、$emit
  • $parent、$children
  • $attrs、$listeners
  • provide、inject
  • eventBus
  • vuex
  • 本地儲存

一、props、$emit單向資料流

超詳細的vue元件間通訊總結

father.vue:

<template>
  <div>
    <div>我是父親:<input type="button" value="父親" /> 數字為: {{num}}</div>
    <son :num="num" @change="change"></son>
  </div>
</template>

<script>
import son from "./son.vue";
export default {
  name: "Father",components: {
    son,},data() {
    return {
      num: 1,};
  },methods:{
    change(val){
      this.num = val
    }
  }
};
</script>

son.vue:

<template>
  <div>我是兒子:<input type="button" value="兒子" @click="change"/>數字為:{{num}}</div>
</template>

<script>
export default {
  name: "App",components: {},props: {
    num: {
      default: 0,created() {},methods: {
    change(){
      // this.num = 2  props通訊是單向資料流,在這直接修改父元件傳過來的num將會報錯    // 可以用$emit觸發change事件,father元件繫結change事件    this.$emit('change',2)
    }
  },};
</script>

超詳細的vue元件間通訊總結

對於上面的場景:子元件的change事件只是為了修改父元件中某一個值,還可以有以下幾種寫法:

1.父元件繫結給子元件的事件使用箭頭函式

father:
<son :num="num" @change="val => num = val"></son>

son:
this.$emit('change',2)

2.update:num和.sync

father:

<son :num.sync="num"></son>

son:

this.$emit('update:num',2)//update是規定的寫法,不可更換

3.v-model

先修改props和繫結的事件:

father:<son :value="num" @input="val => num = val"></son>son:this.$emit('input',2) 
可用v-model簡寫:<son v-model="num"></son>

二、$parent、$children

$parent、$children可直接在父子元件中呼叫各自的方法以及修改資料

子元件中直接:this.$parent.num = 2

父元件中$children是個陣列,因此具體是哪個子元件不太直觀,可以用$refs來操作子元件

vue官方並不推薦使用這種通訊方式:節制地使用$parent$children- 它們的主要目的是作為訪問元件的應急方法,更推薦用 props 和 events 實現父子元件通訊。

三、$attrs、$listeners

$attrs可以拿到父元件傳過來的屬性:

<div>我是兒子:<input type="button" value="兒子" @click="change"/>數字為:{{$attrs}}</div>

超詳細的vue元件間通訊總結

dom節點:

超詳細的vue元件間通訊總結

$attrs會直接將傳過來的屬性放到對應的標籤上,反觀props就不會。如果想去掉標籤中的這些屬性,可以用inheritAttrs:

超詳細的vue元件間通訊總結

值得注意的是:props的優先順序大於$attrs,即當props存在的時候,$attrs為空物件:

超詳細的vue元件間通訊總結

$attrs常用於跨多級元件傳遞屬性,比如祖孫元件,用父元件做中轉:

father:

<son v-bind="$attrs"></son>

$attrs用於屬性跨級傳遞,方法跨級傳遞則用$listeners。

grandFather.vue:

<template>
  <div>
    <div>我是祖父: 數字為:{{nums}}</div>
    <father :nums="nums" @up="up" @down="down"></father>
  </div>
</template>

<script>
import father from "./fhttp://www.cppcns.comather.vue";
export default {
  name: "App",components: {
    father,data(){
    return {
      nums:0
    }
  },methods: {
    up() {
      alert('up')
    },  down() {   alert('down')  },};
</script>

father.vue:

<son v-bind="$attrs" v-on="$listeners"></son>

son.vue:

<div>我是兒子:<input type="button" value="兒子" @click="$listeners.up"/></div>

超詳細的vue元件間通訊總結

四、provide、inject

這對選項需要一起使用,以允許一個祖先元件向其所有子孫後代注入一個依賴,不論元件層次有多深,並在其上下游關係成立的時間裡始終生效

provide選項應該是一個物件或返回一個物件的函式。

inject選項應該是一個字串陣列或一個物件。

App:

...

export default {
  provide(){
    return {vm: this}
  },...

son:

...

export default {
  inject: ['vm'], data(){}, mounted(){  console.log(this.vm) }

...

超詳細的vue元件間通訊總結

注意:provide 和 inject 繫結並不是可響應的。這是LfotakB刻意為之的。然而,如果你傳入了一個可監聽的物件,那麼其物件的 property 還是可響應的。

   inject注入中的值會沿著元件向上查詢,遵從"就近原則"。

   provide 和 inject中的資料流是雙向的。

五、eventBus(事件匯流排)

eventBus通過釋出訂閱全域性事件,供其他元件使用。

在main.中:

Vue.prototype.$bus = new Vue();

parent.vue:

<template>
  <div>
    <son1></son1>
    <son2></son2>
  </div>
</template>

<script>
import son1 from './son1.vue'
import son2 from './son2.vue'
export default {
  name: 'parent',components: {
    son1,son2
  },created(){
     this.$bus.$on('busEvent',(v)=>{
      console.log(v);
    })
  },beforeDestroy(){
    this.$bus.off('busEvent')
  }
}
</script>

son1和son2中的mounted:

son1:mounted(){
  this.$bus.$emit('busEvent','son1哈哈')
}son2:mounted(){  this.$bus.$emit('busEvent','son2嘻嘻')}

列印結果:

超詳細的vue元件間通訊總結

使用eventBus有三點需要注意,1.$bus.on應該在created鉤子內使用,如果在mounted使用,它可能接收不到其他元件來自created鉤子內發出的事件;

               2.$bus.emit應該在mounted中使用,等待creahttp://www.cppcns.comted中的$bus.on事件繫結完成;

               3.釋出訂閱的事件在beforeDestory鉤子裡需要使用$bus.off解除,元件銷燬後沒必要一直監聽。

六、vuex

藉助vuex的狀態管理來實現元件通訊,vuex適用於較為複雜的專案,頻繁的資料共享且資料量比較大。

store/index.js:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    isLogin: false
  },mutations: {
    loginState (state,isLogin) {
      state.isLogin = isLogin
    }
  }
})

export default store

App.vue:

created(){
  this.$store.commit('loginState',true)// 設定登入狀態為true
},

son.vue:

<template>
  <div>我是兒子:<input type="button" value="兒子" />登入狀態:{{isLogin}}</div>
</template>

<script>
import {mapState} from 'vuex';
export default {
  name: "son",computed:{
    ...mapState(['isLogin'])
  }
};
</script>

超詳細的vue元件間通訊總結

七、localstorage

localstorage是瀏覽器的本地儲存,將會長期儲存在瀏覽器中,非常龐大的資料不建議用此方式。

App.vue

created(){
  localStorage.setItem('isLogin',true)
},

son.vue:

computed:{
  isLogin(){
    return localStorage.getItem('isLogin')
  }
}

常見的元件通訊方式基本就是這些啦,有什麼遺漏或不足的,歡迎評論區留言!

總結

到此這篇關於vue元件間通訊的文章就介紹到這了,更多相關vue元件間通訊內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!