欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入了解Vue組件七種通信方式

 更新時(shí)間:2021年12月24日 15:59:10   作者:前端進(jìn)階之旅  
vue組件通信的方式,這是在面試中一個(gè)非常高頻的問題。其實(shí)Vue組件的通信方式除了props和?$emit還有很多,本文將對(duì)vue組件通信方式進(jìn)行一下總結(jié),感興趣的可以學(xué)習(xí)一下

vue組件通信的方式,這是在面試中一個(gè)非常高頻的問題,我剛開始找實(shí)習(xí)便經(jīng)常遇到這個(gè)問題,當(dāng)時(shí)只知道回到props和 $emit,后來隨著學(xué)習(xí)的深入,才發(fā)現(xiàn)vue組件的通信方式竟然有這么多!

今天對(duì)vue組件通信方式進(jìn)行一下總結(jié),如寫的有疏漏之處還請(qǐng)大家留言。

1. props/$emit

簡介

props和 $emit相信大家十分的熟悉了,這是我們最常用的vue通信方式。

props:props可以是數(shù)組或?qū)ο?,用于接收來自父組件通過v-bind傳遞的數(shù)據(jù)。當(dāng)props為數(shù)組時(shí),直接接收父組件傳遞的屬性;當(dāng) props 為對(duì)象時(shí),可以通過type、default、required、validator等配置來設(shè)置屬性的類型、默認(rèn)值、是否必傳和校驗(yàn)規(guī)則。

$emit:在父子組件通信時(shí),我們通常會(huì)使用 $emit來觸發(fā)父組件v-on在子組件上綁定相應(yīng)事件的監(jiān)聽。

代碼實(shí)例

下面通過代碼來實(shí)現(xiàn)一下props和 $emit的父子組件通信,在這個(gè)實(shí)例中,我們都實(shí)現(xiàn)了以下的通信:

父向子傳值:父組件通過 :messageFromParent="message" 將父組件 message 值傳遞給子組件,當(dāng)父組件的 input 標(biāo)簽輸入時(shí),子組件p標(biāo)簽中的內(nèi)容就會(huì)相應(yīng)改變。

子向父傳值:父組件通過 @on-receive="receive" 在子組件上綁定了 receive 事件的監(jiān)聽,子組件 input 標(biāo)簽輸入時(shí),會(huì)觸發(fā) receive 回調(diào)函數(shù), 通過 this.$emit('on-receive', this.message) 將子組件 message 的值賦值給父組件 messageFromChild ,改變父組件p標(biāo)簽的內(nèi)容。

請(qǐng)看代碼:

// 子組件代碼
<template>
  <div class="child">
    <h4>this is child component</h4>
    <input type="text" v-model="message" @keyup="send" />
    <p>收到來自父組件的消息:{{ messageFromParent }}</p>
  </div>
</template>
<script>
export default {
  name: 'Child',
  props: ['messageFromParent'],  // 通過props接收父組件傳過來的消息
  data() {
    return {
      message: '',
    }
  },
  methods: {
    send() {
      this.$emit('on-receive', this.message)  // 通過 $emit觸發(fā)on-receive事件,調(diào)用父組件中receive回調(diào),并將this.message作為參數(shù)
    },
  },
}
</script>
// 父組件代碼
<template>
  <div class="parent">
    <h3>this is parent component</h3>
    <input type="text" v-model="message" />
    <p>收到來自子組件的消息:{{ messageFromChild }}</p>
    <Child :messageFromParent="message" @on-receive="receive" />
  </div>
</template>
<script>
import Child from './child'
export default {
  name: 'Parent',
  data() {
    return {
      message: '', // 傳遞給子組件的消息
      messageFromChild: '',
    }
  },
  components: {
    Child,
  },
  methods: {
    receive(msg) { // 接受子組件的信息,并將其賦值給messageFromChild
      this.messageFromChild = msg
    },
  },
}
</script>

效果預(yù)覽

2. v-slot

簡介

v-slot是 Vue2.6 版本中新增的用于統(tǒng)一實(shí)現(xiàn)插槽和具名插槽的api,用于替代 slot(2.6.0廢棄) 、 slot-scope(2.6.0廢棄) 、 scope(2.5.0廢棄) 等api。

v-slot在 template 標(biāo)簽中用于提供具名插槽或需要接收 prop 的插槽,如果不指定 v-slot ,則取默認(rèn)值 default 。

代碼實(shí)例

下面請(qǐng)看v-slot的代碼實(shí)例,在這個(gè)實(shí)例中我們實(shí)現(xiàn)了:

父向子傳值:父組件通過 <template v-slot:child>{{ message }}</template> 將父組件的message值傳遞給子組件,子組件通過 <slot name="child"></slot> 接收到相應(yīng)內(nèi)容,實(shí)現(xiàn)了父向子傳值。

// 子組件代碼
<template>
  <div class="child">
    <h4>this is child component</h4>
    <p>收到來自父組件的消息:
      <slot name="child"></slot>  <!--展示父組件通過插槽傳遞的{{message}}-->
    </p>
  </div>
</template>
<template>
  <div class="parent">
    <h3>this is parent component</h3>
    <input type="text" v-model="message" />
    <Child>
      <template v-slot:child>
        {{ message }}  <!--插槽要展示的內(nèi)容-->
      </template>
    </Child>
  </div>
</template>
<script>
import Child from './child'
export default {
  name: 'Parent',
  data() {
    return {
      message: '',
    }
  },
  components: {
    Child,
  },
}
</script>

效果預(yù)覽

3. $refs/? $parent/ $children/$root

簡介

我們也同樣可以通過 $refs/$parent/$children/$root 等方式獲取 Vue 組件實(shí)例,得到實(shí)例上綁定的屬性及方法等,來實(shí)現(xiàn)組件之間的通信。

$refs:我們通常會(huì)將 $refs綁定在DOM元素上,來獲取DOM元素的 attributes。在實(shí)現(xiàn)組件通信上,我們也可以將 $refs 綁定在子組件上,從而獲取子組件實(shí)例。

$parent:我們可以在 Vue 中直接通過 this.$parent 來獲取當(dāng)前組件的父組件實(shí)例(如果有的話)。

$children:同理,我們也可以在 Vue 中直接通過 this.$children 來獲取當(dāng)前組件的子組件實(shí)例的數(shù)組。但是需要注意的是, this.$children 數(shù)組中的元素下標(biāo)并不一定對(duì)用父組件引用的子組件的順序,例如有異步加載的子組件,可能影響其在 children 數(shù)組中的順序。所以使用時(shí)需要根據(jù)一定的條件例如子組件的name去找到相應(yīng)的子組件。

$root:獲取當(dāng)前組件樹的根 Vue 實(shí)例。如果當(dāng)前實(shí)例沒有父實(shí)例,此實(shí)例將會(huì)是其自己。通過 $root ,我們可以實(shí)現(xiàn)組件之間的跨級(jí)通信。

代碼實(shí)例

下面來看一個(gè) $ parent 和 $ children 使用的實(shí)例(由于這幾個(gè)api的使用方式大同小異,所以關(guān)于 $ refs 和? $ root 的使用就不在這里展開了,在這個(gè)實(shí)例中實(shí)現(xiàn)了:

父向子傳值:子組件通過 $parent.message 獲取到父組件中message的值。

子向父傳值:父組件通過 $children 獲取子組件實(shí)例的數(shù)組,在通過對(duì)數(shù)組進(jìn)行遍歷,通過實(shí)例的 name 獲取到對(duì)應(yīng) Child1 子組件實(shí)例將其賦值給 child1,然后通過 child1.message 獲取到 Child1 子組件的message。

代碼如下:

// 子組件
<template>
  <div class="child">
    <h4>this is child component</h4>
    <input type="text" v-model="message" />
    <p>收到來自父組件的消息:{{ $parent.message }}</p>  <!--展示父組件實(shí)例的message-->
  </div>
</template>
<script>
export default {
  name: 'Child1',
  data() {
    return {
      message: '',   // 父組件通過this.$children可以獲取子組件實(shí)例的message
    }
  },
}
</script>
// 父組件
<template>
  <div class="parent">
    <h3>this is parent component</h3>
    <input type="text" v-model="message" />
    <p>收到來自子組件的消息:{{ child1.message }}</p> <!--展示子組件實(shí)例的message-->
    <Child />
  </div>
</template>
<script>
import Child from './child'
export default {
  name: 'Parent',
  data() {
    return {
      message: '',
      child1: {},
    }
  },
  components: {
    Child,
  },
  mounted() {
    this.child1 = this.$children.find((child) => {
      return child.$options.name === 'Child1'  // 通過options.name獲取對(duì)應(yīng)name的child實(shí)例
    })
  },
}
</script>

效果預(yù)覽

4. $attrs/$listener

簡介

$ attrs和 $ listeners 都是 Vue2.4 中新增加的屬性,主要是用來供使用者用來開發(fā)高級(jí)組件的。

$attrs:用來接收父作用域中不作為 prop 被識(shí)別的 attribute 屬性,并且可以通過 v-bind="$attrs" 傳入內(nèi)部組件——在創(chuàng)建高級(jí)別的組件時(shí)非常有用。

試想一下,當(dāng)你創(chuàng)建了一個(gè)組件,你要接收 param1 、param2、param3 …… 等數(shù)十個(gè)參數(shù),如果通過 props,那你需要通過 props: ['param1', 'param2', 'param3', ……] 等聲明一大堆。如果這些 props 還有一些需要往更深層次的子組件傳遞,那將會(huì)更加麻煩。

而使用 $attrs ,你不需要任何聲明,直接通過 $attrs.param1 、 $attrs.param2 ……就可以使用,而且向深層子組件傳遞上面也給了示例,十分方便。

$listeners:包含了父作用域中的 v-on 事件監(jiān)聽器。它可以通過 v-on="$listeners" 傳入內(nèi)部組件——在創(chuàng)建更高層次的組件時(shí)非常有用,這里在傳遞時(shí)的使用方法和 $attrs 十分類似。

代碼實(shí)例

在這個(gè)實(shí)例中,共有三個(gè)組件:A、B、C,其關(guān)系為:[ A [ B [C] ] ],A為B的父組件,B為C的父組件。即:1級(jí)組件A,2級(jí)組件B,3級(jí)組件C。我們實(shí)現(xiàn)了:

父向子傳值:1級(jí)組件A通過 :messageFromA="message" 將 message 屬性傳遞給2級(jí)組件B,2級(jí)組件B通過 $attrs.messageFromA 獲取到1級(jí)組件A的 message 。

:messageFromA="message"
v-bind="$attrs"
$attrs.messageFromA

子向父傳值:1級(jí)組件A通過 @keyup="receive" 在子孫組件上綁定keyup事件的監(jiān)聽,2級(jí)組件B在通過 v-on="$listeners" 來將 keyup 事件綁定在其 input 標(biāo)簽上。當(dāng)2級(jí)組件B input 輸入框輸入時(shí),便會(huì)觸發(fā)1級(jí)組件A的receive回調(diào),將2級(jí)組件B的 input 輸入框中的值賦值給1級(jí)組件A的 messageFromComp ,從而實(shí)現(xiàn)子向父傳值。

@keyup="receive"
<CompC v-on="$listeners" />
v-on="$listeners"

代碼如下:

// 3級(jí)組件C
<template>
  <div class="compc">
    <h5>this is C component</h5>
    <input name="compC" type="text" v-model="message" v-on="$listeners" /> <!--將A組件keyup的監(jiān)聽回調(diào)綁在該input上-->
    <p>收到來自A組件的消息:{{ $attrs.messageFromA }}</p>
  </div>
</template>
<script>
export default {
  name: 'Compc',
  data() {
    return {
      message: '',
    }
  },
}
</script>
// 2級(jí)組件B
<template>
  <div class="compb">
    <h4>this is B component</h4>
    <input name="compB" type="text" v-model="message" v-on="$listeners" />  <!--將A組件keyup的監(jiān)聽回調(diào)綁在該input上-->
    <p>收到來自A組件的消息:{{ $attrs.messageFromA }}</p>
    <CompC v-bind="$attrs" v-on="$listeners" /> <!--將A組件keyup的監(jiān)聽回調(diào)繼續(xù)傳遞給C組件,將A組件傳遞的attrs繼續(xù)傳遞給C組件-->
  </div>
</template>
<script>
import CompC from './compC'
export default {
  name: 'CompB',
  components: {
    CompC,
  },
  data() {
    return {
      message: '',
    }
  },
}
</script>
// A組件
<template>
  <div class="compa">
    <h3>this is A component</h3>
    <input type="text" v-model="message" />
    <p>收到來自{{ comp }}的消息:{{ messageFromComp }}</p>
    <CompB :messageFromA="message" @keyup="receive" />  <!--監(jiān)聽子孫組件的keyup事件,將message傳遞給子孫組件-->
  </div>
</template>
<script>
import CompB from './compB'
export default {
  name: 'CompA',
  data() {
    return {
      message: '',
      messageFromComp: '',
      comp: '',
    }
  },
  components: {
    CompB,
  },
  methods: {
    receive(e) { // 監(jiān)聽子孫組件keyup事件的回調(diào),并將keyup所在input輸入框的值賦值給messageFromComp
      this.comp = e.target.name
      this.messageFromComp = e.target.value
    },
  },
}
</script>

效果預(yù)覽

5. provide/inject

簡介

provide/inject這對(duì)選項(xiàng)需要一起使用,以允許一個(gè)祖先組件向其所有子孫后代注入一個(gè)依賴,不論組件層次有多深,并在其上下游關(guān)系成立的時(shí)間里始終生效。如果你是熟悉React的同學(xué),你一定會(huì)立刻想到Context這個(gè)api,二者是十分相似的。

provide:是一個(gè)對(duì)象,或者是一個(gè)返回對(duì)象的函數(shù)。該對(duì)象包含可注入其子孫的 property ,即要傳遞給子孫的屬性和屬性值。

injcet:一個(gè)字符串?dāng)?shù)組,或者是一個(gè)對(duì)象。當(dāng)其為字符串?dāng)?shù)組時(shí),使用方式和props十分相似,只不過接收的屬性由data變成了provide中的屬性。當(dāng)其為對(duì)象時(shí),也和props類似,可以通過配置default和from等屬性來設(shè)置默認(rèn)值,在子組件中使用新的命名屬性等。

代碼實(shí)例

這個(gè)實(shí)例中有三個(gè)組件,1級(jí)組件A,2級(jí)組件B,3級(jí)組件C:[ A [ B [C] ] ],A是B的父組件,B是C的父組件。實(shí)例中實(shí)現(xiàn)了:

父向子傳值:1級(jí)組件A通過provide將message注入給子孫組件,2級(jí)組件B通過 inject: ['messageFromA'] 來接收1級(jí)組件A中的message,并通過 messageFromA.content 獲取1級(jí)組件A中message的content屬性值。

跨級(jí)向下傳值:1級(jí)組件A通過provide將message注入給子孫組件,3級(jí)組件C通過 inject: ['messageFromA'] 來接收1級(jí)組件A中的message,并通過 messageFromA.content 獲取1級(jí)組件A中message的content屬性值,實(shí)現(xiàn)跨級(jí)向下傳值。

代碼如下:

// 1級(jí)組件A
<template>
  <div class="compa">
    <h3>this is A component</h3>
    <input type="text" v-model="message.content" />
    <CompB />
  </div>
</template>
<script>
import CompB from './compB'
export default {
  name: 'CompA',
  provide() {
    return {
      messageFromA: this.message,  // 將message通過provide傳遞給子孫組件
    }
  },
  data() {
    return {
      message: {
        content: '',
      },
    }
  },
  components: {
    CompB,
  },
}
</script>
// 2級(jí)組件B
<template>
  <div class="compb">
    <h4>this is B component</h4>
    <p>收到來自A組件的消息:{{ messageFromA && messageFromA.content }}</p>
    <CompC />
  </div>
</template>
<script>
import CompC from './compC'
export default {
  name: 'CompB',
  inject: ['messageFromA'], // 通過inject接受A中provide傳遞過來的message
  components: {
    CompC,
  },
}
</script>
// 3級(jí)組件C
<template>
  <div class="compc">
    <h5>this is C component</h5>
    <p>收到來自A組件的消息:{{ messageFromA && messageFromA.content }}</p>
  </div>
</template>
<script>
export default {
  name: 'Compc',
  inject: ['messageFromA'], // 通過inject接受A中provide傳遞過來的message
}
</script>

注意點(diǎn):

可能有同學(xué)想問我上面1級(jí)組件A中的message為什么要用object類型而不是string類型,因?yàn)樵趘ue provide 和 inject 綁定并不是可響應(yīng)的。如果message是string類型,在1級(jí)組件A中通過input輸入框改變message值后無法再賦值給messageFromA,如果是object類型,當(dāng)對(duì)象屬性值改變后,messageFromA里面的屬性值還是可以隨之改變的,子孫組件inject接收到的對(duì)象屬性值也可以相應(yīng)變化。

子孫provide和祖先同樣的屬性,會(huì)在后代中覆蓋祖先的provide值。例如2級(jí)組件B中也通過provide向3級(jí)組件C中注入一個(gè)messageFromA的值,則3級(jí)組件C中的messageFromA會(huì)優(yōu)先接收2級(jí)組件B注入的值而不是1級(jí)組件A。

效果預(yù)覽

6. eventBus

簡介

eventBus又稱事件總線,通過注冊(cè)一個(gè)新的Vue實(shí)例,通過調(diào)用這個(gè)實(shí)例的 $ emit 和 $ on等來監(jiān)聽和觸發(fā)這個(gè)實(shí)例的事件,通過傳入?yún)?shù)從而實(shí)現(xiàn)組件的全局通信。它是一個(gè)不具備 DOM 的組件,有的僅僅只是它實(shí)例方法而已,因此非常的輕便。

我們可以通過在全局Vue實(shí)例上注冊(cè):

// main.js
Vue.prototype.$Bus = new Vue()

但是當(dāng)項(xiàng)目過大時(shí),我們最好將事件總線抽象為單個(gè)文件,將其導(dǎo)入到需要使用的每個(gè)組件文件中。這樣,它不會(huì)污染全局命名空間:

// bus.js,使用時(shí)通過import引入
import Vue from 'vue'
export const Bus = new Vue()

原理分析

eventBus的原理其實(shí)比較簡單,就是使用訂閱-發(fā)布模式,實(shí)現(xiàn) $ emit 和 $ on兩個(gè)方法即可:

// eventBus原理
export default class Bus {
  constructor() {
    this.callbacks = {}
  }
  $on(event, fn) {
    this.callbacks[event] = this.callbacks[event] || []
    this.callbacks[event].push(fn)
  }
  $emit(event, args) {
    this.callbacks[event].forEach((fn) => {
      fn(args)
    })
  }
}

// 在main.js中引入以下
// Vue.prototype.$bus = new Bus()

代碼實(shí)例

在這個(gè)實(shí)例中,共包含了4個(gè)組件:[ A [ B [ C、D ] ] ],1級(jí)組件A,2級(jí)組件B,3級(jí)組件C和3級(jí)組件D。我們通過使用eventBus實(shí)現(xiàn)了:

全局通信:即包括了父子組件相互通信、兄弟組件相互通信、跨級(jí)組件相互通信。4個(gè)組件的操作邏輯相同,都是在input輸入框時(shí),通過 this.$bus.$emit('sendMessage', obj) 觸發(fā)sendMessage事件回調(diào),將sender和message封裝成對(duì)象作為參數(shù)傳入;同時(shí)通過 this.$bus.$on('sendMessage', obj) 監(jiān)聽其他組件的sendMessage事件,實(shí)例當(dāng)前組件示例sender和message的值。這樣任一組件input輸入框值改變時(shí),其他組件都能接收到相應(yīng)的信息,實(shí)現(xiàn)全局通信。

代碼如下:

// main.js
Vue.prototype.$bus = new Vue()
// 1級(jí)組件A
<template>  
  <div class="containerA">   
    <h2>this is CompA</h2>  
    <input type="text" v-model="message" @keyup="sendMessage" />   
    <p v-show="messageFromBus && sender !== $options.name">      
      收到{{ sender }}的消息:{{ messageFromBus }}   
    </p>   
    <CompB /> 
  </div>
</template>
<script>
import CompB from './compB'
export default {  
  name: 'CompA', 
  components: {   
    CompB,  
  },  
  data() {  
    return {    
      message: '',    
      messageFromBus: '',      
      sender: '',   
    } 
  },  
  mounted() {   
    this.$bus.$on('sendMessage', (obj) => {  // 通過eventBus監(jiān)聽sendMessage事件     
      const { sender, message } = obj    
      this.sender = sender     
      this.messageFromBus = message  
    }) 
  }, 
  methods: {  
    sendMessage() {     
      this.$bus.$emit('sendMessage', { // 通過eventBus觸發(fā)sendMessage事件     
        sender: this.$options.name,     
        message: this.message,   
      })   
    }, 
  },
}
</script>
// 2級(jí)組件B
<template> 
  <div class="containerB">   
    <h3>this is CompB</h3>  
    <input type="text" v-model="message" @keyup="sendMessage" />  
    <p v-show="messageFromBus && sender !== $options.name">     
      收到{{ sender }}的消息:{{ messageFromBus }}  
    </p>  
    <CompC />  
    <CompD /> 
  </div>
</template>
<script>
import CompC from './compC'
import CompD from './compD'
export default { 
  name: 'CompB', 
  components: {  
    CompC,  
    CompD,  
  }, 
  data() {  
    return {    
      message: '',   
      messageFromBus: '',    
      sender: '',   
    } 
  }, 
  mounted() {    
    this.$bus.$on('sendMessage', (obj) => { // 通過eventBus監(jiān)聽sendMessage事件     
      const { sender, message } = obj     
      this.sender = sender     
      this.messageFromBus = message  
    }) 
  }, 
  methods: {  
    sendMessage() {   
      this.$bus.$emit('sendMessage', { // 通過eventBus觸發(fā)sendMessage事件      
        sender: this.$options.name,    
        message: this.message,    
     })   
   },  
 },
}
</script>
// 3級(jí)組件C
<template> 
  <div class="containerC">  
    <p>this is CompC</p>   
    <input type="text" v-model="message" @keyup="sendMessage" />   
    <p v-show="messageFromBus && sender !== $options.name">      
      收到{{ sender }}的消息:{{ messageFromBus }}  
    </p> 
  </div>
</template>
<script>
export default {  
  name: 'CompC',
  data() {   
    return {   
      message: '',   
      messageFromBus: '',   
      sender: '',   
    } 
  }, 
  mounted() {  
    this.$bus.$on('sendMessage', (obj) => { // 通過eventBus監(jiān)聽sendMessage事件    
      const { sender, message } = obj    
      this.sender = sender    
      this.messageFromBus = message   
    })  
  },
  methods: {   
    sendMessage() {    
      this.$bus.$emit('sendMessage', { // 通過eventBus觸發(fā)sendMessage事件       
        sender: this.$options.name,     
        message: this.message,     
      })   
    }, 
  },
}
</script>
// 3級(jí)組件D
<template> 
  <div class="containerD">   
    <p>this is CompD</p>   
    <input type="text" v-model="message" @keyup="sendMessage" />   
    <p v-show="messageFromBus && sender !== $options.name">     
      收到{{ sender }}的消息:{{ messageFromBus }} 
    </p> 
  </div>
</template>
<script>
export default { 
  name: 'CompD', 
  data() {  
    return {   
      message: '',   
      messageFromBus: '',   
      sender: '',   
    } 
  }, 
  mounted() {   
    this.$bus.$on('sendMessage', (obj) => { // 通過eventBus監(jiān)聽sendMessage事件     
      const { sender, message } = obj    
      this.sender = sender   
      this.messageFromBus = message   
    }) 
  }, 
  methods: {  
    sendMessage() {   
      this.$bus.$emit('sendMessage', { // 通過eventBus觸發(fā)sendMessage事件       
        sender: this.$options.name,     
        message: this.message,   
      })  
    }, 
  },
}
</script>

效果預(yù)覽

圖片過大,截圖處理

7. Vuex

當(dāng)項(xiàng)目龐大以后,在多人維護(hù)同一個(gè)項(xiàng)目時(shí),如果使用事件總線進(jìn)行全局通信,容易讓全局的變量的變化難以預(yù)測(cè)。于是有了Vuex的誕生。

Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測(cè)的方式發(fā)生變化。

有關(guān)Vuex的內(nèi)容,可以參考 Vuex官方文檔 [1] ,我就不在這里班門弄斧了,直接看代碼。

代碼實(shí)例

Vuex的實(shí)例和事件總線leisi,同樣是包含了4個(gè)組件:[ A [ B [ C、D ] ] ],1級(jí)組件A,2級(jí)組件B,3級(jí)組件C和3級(jí)組件D。我們?cè)谶@個(gè)實(shí)例中實(shí)現(xiàn)了:

全局通信:代碼的內(nèi)容和eventBus也類似,不過要比eventBus使用方便很多。每個(gè)組件通過watch監(jiān)聽input輸入框的變化,把input的值通過vuex的commit觸發(fā)mutations,從而改變stroe的值。然后每個(gè)組件都通過computed動(dòng)態(tài)獲取store中的數(shù)據(jù),從而實(shí)現(xiàn)全局通信。

// store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
  state: {
    message: {
      sender: '',
      content: '',
    },
  },
  mutations: {
    sendMessage(state, obj) {
      state.message = {
        sender: obj.sender,
        content: obj.content,
      }
    },
  },
})
// 組件A
<template>
  <div class="containerA">
    <h2>this is CompA</h2>
    <input type="text" v-model="message" />
    <p v-show="messageFromStore && sender !== $options.name">
      收到{{ sender }}的消息:{{ messageFromStore }}
    </p>
    <CompB />
  </div>
</template>
<script>
import CompB from './compB'
export default {
  name: 'CompA',
  components: {
    CompB,
  },
  data() {
    return {
      message: '',
    }
  },
  computed: {
    messageFromStore() {
      return this.$store.state.message.content
    },
    sender() {
      return this.$store.state.message.sender
    },
  },
  watch: {
    message(newValue) {
      this.$store.commit('sendMessage', {
        sender: this.$options.name,
        content: newValue,
      })
    },
  },
}
</script>

同樣和eventBus中一樣,B,C,D組件中的代碼除了引入子組件的不同,script部分都是一樣的,就不再往上寫了。

效果預(yù)覽

總結(jié)

上面總共提到了7中Vue的組件通信方式,他們能夠進(jìn)行的通信種類如下圖所示:

  • props/$emit:可以實(shí)現(xiàn)父子組件的雙向通信,在日常的父子組件通信中一般會(huì)作為我們的最常用選擇。
  • v-slot:可以實(shí)現(xiàn)父子組件單向通信(父向子傳值),在實(shí)現(xiàn)可復(fù)用組件,向組件中傳入DOM節(jié)點(diǎn)、html等內(nèi)容以及某些組件庫的表格值二次處理等情況時(shí),可以優(yōu)先考慮v-slot。
  • $ refs/$ parent/ $ children/ $ r oot: 可 以實(shí)現(xiàn)父子組件雙向通信,其中 $root可以實(shí)現(xiàn)根組件實(shí)例向子孫組件跨級(jí)單向傳值。 在父組件沒有傳遞值或通過v-on綁定監(jiān)聽時(shí),父子間想要獲取彼此的屬性或方法可以考慮使用這些api。
  • $ attrs/ $ listeners: 能夠?qū)崿F(xiàn)跨級(jí)雙向通信,能夠讓你簡單的獲取傳入的屬性和綁定的監(jiān)聽,并且方便地向下級(jí)子組件傳遞,在構(gòu)建高級(jí)組件時(shí)十分好用。
  • provide/inject:可以實(shí)現(xiàn)跨級(jí)單向通信,輕量地向子孫組件注入依賴,這是你在實(shí)現(xiàn)高級(jí)組件、創(chuàng)建組件庫時(shí)的不二之選。
  • eventBus:可以實(shí)現(xiàn)全局通信,在項(xiàng)目規(guī)模不大的情況下,可以利用eventBus實(shí)現(xiàn)全局的事件監(jiān)聽。但是eventBus要慎用,避免全局污染和內(nèi)存泄漏等情況。
  • Vuex:可以實(shí)現(xiàn)全局通信,是vue項(xiàng)目全局狀態(tài)管理的最佳實(shí)踐。在項(xiàng)目比較龐大,想要集中式管理全局組件狀態(tài)時(shí),那么安裝Vuex準(zhǔn)沒錯(cuò)!

?以上就是深入了解Vue組件七種通信方式的詳細(xì)內(nèi)容,更多關(guān)于Vue組件通信方式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論