1. 程式人生 > 程式設計 >詳解vue元件之間的通訊

詳解vue元件之間的通訊

說明:下面我總結了比較常用的vue元件之前通訊的方式,最近準備面試,所以有些總結貼上來分享

props和$emit

只有父子關係才可以用這種方式,父元件向子元件傳遞引數用props,子向父傳遞使用觸發$emit自定義事件

1.props

<!-- parent.vue,可以傳遞`靜態`的props和`動態`的props,靜態的引數只能是個String型別的,如果是其他型別的一定要記得加`:`來表示這是一個 js 表示式而不是一個字串 -->
<Child :name="name" :age="18" address="xxxxx"></Child>
...
data () {
 return {
  name: 'marry'
 }
}

<!-- 傳一個引數所有props,雖然目前我沒有這個需求,使用不帶引數的 v-bind -->
<blog-post v-bind="post"></blog-post>
post: {
 id: 1,title: 'My Journey with Vue'
}
//等價於下面
<blog-post
 v-bind:id="post.id"
 v-bind:title="post.title"
></blog-post>


<!-- child.vue -->
...
//以字串陣列形式列出的 prop
props: ['name','age','address']

//prop驗證,當 prop 驗證失敗的時候,(開發環境構建版本的) Vue 將會產生一個控制檯的警告
//注意:以下型別不能寫成'String'這種帶引號的形式
props: {
 // 基礎的型別檢查 (`null` 和 `undefined` 會通過任何型別驗證)
 propA: Number,// 多個可能的型別
 propB: [String,Number],// 必填的字串
 propC: {
  type: String,required: true
 },// 帶有預設值的數字
 propD: {
  type: Number,default: 100
 },// 帶有預設值的物件
 propE: {
  type: Object,// 物件或陣列預設值必須從一個工廠函式獲取
  default: function () {
  return { message: 'hello' }
  }
 },// 自定義驗證函式
 propF: {
  validator: function (value) {
  // 這個值必須匹配下列字串中的一個
  return ['success','warning','danger'].indexOf(value) !== -1
  }
 }
}
//注意那些 prop 會在一個元件例項建立之前進行驗證,所以例項的 property (如 data、computed 等) 在 default 或 validator 函式中是不可用的。

2.$emit

<!-- parent.vue -->
<Child @my-event="myEvent"></Child>
...
methods: {
 myEvent(name){
 this.name = name
 }
}

<!-- child.vue -->
<div>
 <button @click="$emit('my-event',name)"></button>
</div>
//使用自定義事件將子元件的值拋給父元件

中央事件匯流排 bus

用於解決跨級和兄弟元件通訊問題,巧妙的使用一個公共的vue例項,利用$on,$emit,$off(移除自定義事件監聽器)

方法一:

可以在main.js中,在Vue的原型上掛載一個公共的Vue例項 $bus,這樣全域性任何一個地方都可以使用

Vue.prototype.$bus = new Vue()

然後在需要的地方註冊自定義事件和接收引數的回撥函式

this.$bus.$on('changeName',name => {
 this.name = name
})

在需要改變的時候觸發事件並丟擲引數

this.$bus.$emit('changeName','wzj')

方法二:

定義一個util.js檔案

import Vue from 'vue'

const bus = new Vue()
export default bus

在需要用到bus的檔案中引入

import bus from '../util' //檔案路徑不一定

//在一個檔案定義事件
bus.$on('changeName',name => {
 this.name = name
})

//另一個檔案丟擲引數
bus.$emit('changeName','wzj')

vuex

對於專案比較複雜,多元件共享狀態,不同層級需要通訊

詳解vue元件之間的通訊

核心概念:

state,getter,mutation,action,module

//store/index.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export dafault new Vuex.Store({
 state: {
 name: '',age: 0
 },getters: {
 tranName(state){
  return 'name: ' + state.name
 }
 },mutations: {
 changeName(state,name){
  state.name = name
 }
 },/*Action 函式接受一個與 store 例項具有相同方法和屬性的 context 物件,因此你可以呼叫 context.commit 提交一個 mutation,或者通過 context.state 和 context.getters 來獲取 state 和 getters */
 actions: { //非同步函式,但還是要通過提交commit觸發mutations函式操作state
 changeName(context,name){
  context.commit('changeName',name)
 }
 },modules: {}
})

在元件中使用

方法一:

//訪問state屬性
this.$store.state.name
//訪問getters屬性
this.$store.getters.tranName
//訪問mutations
this.$store.commit('changeName','wzj')
//訪問actions
this.$store.dispatch('changeName','wzj')

方法二:使用輔助函式對映到本地,這裡只列舉了簡便的方式,更多查閱官網咖

import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
//state 和 getters 對映到本地的computed屬性中,作為計算屬性使用
computed: {
 ...mapState(['name','age']),...mapGetters(['tranName'])
}

//mutations 和 actions
methods: {
 // 將 `this.changeName()` 對映為 `this.$store.commit('changeName')`
 ...mapMutations(['changeName']) 
 // 將 `this.changeName()` 對映為 `this.$store.dispatch('changeName')`
 ...mapActions(['changeName'])
}

$attrs 和 $listeners

父元件與後代元件,用以上方法有點大材小用或者第一種有些不方便

  • $attrs 包含了父作用域中不作為 prop 被識別 (且獲取) 的 attribute 繫結 ( class 和 style 除外)。當一個元件沒有宣告任何 prop 時,這裡會包含所有父作用域的繫結 ( class 和 style 除外),並且可以通過 v-bind="$attrs" 傳入內部元件。
  • $listeners 包含了父作用域中的 (不含 .native 修飾器的) v-on 事件監聽器。它可以通過 v-on="$listeners" 傳入內部元件——在建立更高層次的元件時非常有用。

例子:

//app.vue
<div>
 <One name="wzj" :age="age" address="xian" @changeAge="changeAge"></One>
</div>
...
data(){
 return {
 age: 10
 }
},methods: {
 changeAge(age){
 this.age = age
 }
}

//one.vue
<div>
 <div>姓名:{{ name }}</div>
 <div>年齡:{{ age }}</div>
 <Two v-bind="$attrs" v-on="$listeners"></Two>
 <button @click="change">點我2</button>
</div>
...
props: ['name','age'],//two.vue
<div>
 <div>{{ address }}</div>
 <button @click="change">點我2</button>
</div>
...
props: ['address'],//用$attrs傳遞到最後的屬性,在使用的時候還是要宣告props
methods: {
 change(){
 this.$emit('changeAge',30)
 }
}

理解:其實祖先元件的屬性和事件還是一層層往下傳,不過用$attrs 和 $listeners優化和簡便了傳遞過程中書寫,而且在傳遞的過程中,任何一個聲明瞭 $listeners的元件都可以觸發裡面的所有事件,而聲明瞭$attrs的元件只能使用之前未用props宣告的剩下的屬性。

以上就是vue元件之間的通訊的詳細內容,更多關於vue 元件通訊的資料請關注我們其它相關文章!