Vue組件通訊全記錄

Vue Component 相比React受控組件的概念,Vue組件之間的「通訊」特徵則表現的更強。javascript

這種「通訊」特性表如今,組件內部擁有一套本身的狀態管理,對外只表現爲信息的傳遞,而不須要外部組件特地作出什麼行爲(例如受控組件的狀態徹底是由控制者決定,受控組件狀態的改變必需要求控制者作出響應的行爲)vue

除了常見的父子級別通訊,還有兄弟級、跨級,到總線和Vuex。不得不說Vue組件通訊的方式要更豐富一些。java

父組件給子組件傳消息

1. 屬性props

 最基礎的父傳子手段。vuex

// child指定props
export default {
  props: {
    msg: String
  }
}

// parent傳遞消息
<child msg='msg' />
複製代碼

2. 引用refchildren

直接獲取子組件引用來設置子組件的內部值。children是一個數組,裝着全部自定義子組件,但多個子組件狀況下排列不能保證順序。因此更可靠的仍是子組件制定ref,父組件使用$refs獲取子組件引用。數組

// child
export default {
  data() {
    return {
      // parent msg by $refs
      // or
      // parent msg by $children
      current: ''
    }
  }
}

// parent
<child ref="child">
export default {
  methods: {
    handleChange1() {
      this.$refs.child.current = 'parent msg by $refs'
    },
    handleChange2() {
      this.$children[0].current = 'parent msg by $children'
    }
  },
  mounted() {
    // this.handleChange1()
    // or
    // this.handleChange2() 
  }
}
複製代碼

子組件給父組件傳消息

1. 自定義事件

最核心的向上傳遞消息的手段markdown

// child
<button @click="sendMsg" />
export default {
  methods: {
    sendMsg() {
      this.$emit('sendMsg', { msg: 'msg' })
    }
  }
}

// parent
<child @send-msg="receiveMsg" />
export default {
  methods: {
    receiveMsg(param) {
      console.log(param) // { msg: 'msg' } 
    }
  }
}
複製代碼

v-model.sync的本質也是props➕自定義事件的組合數據結構

祖先組件給後代組件傳消息

1. 特性$attr

傳遞那些子組件沒有設定在props裏面的值,一般在子組件中使用inheritAttrs: false來取消非props值在根組件上的繼承。不過$attrs特殊的是,能夠在「族譜」中一直向後傳遞信息:每一個成員使用v-bind="$attrs"均可以將祖先的非props屬性傳遞下去。ide

// grandson
export default {
 mounted() {
   console.log(this.$attrs.attr) // attr
 }
}

// child
<grandson v-bing="$attrs" />
export default {
  props: {
    msg: String
  },
  mounted() {
    console.log(this.msg, this.$attrs.attr) // props, attr
  }
}

// parent傳遞props消息和attrs消息
<child msg="prop" attr="attr" />
複製代碼

2. 提供和注入provide/inject

一個祖先向全部後代提供消息的手段,沒必要由每一代傳遞消息oop

// grandson
export default {
  inject: ['msg'],
  mounted() {
    console.log(this.msg) // 'msg'
  }
}

// child
<grandson />

// parent
<child />
export default {
  provide() {
    return {
      msg: 'msg'
    }
  }
}
複製代碼

後代組件給祖先組件傳消息

1. 監聽器$listeners

$listeners能夠一直向後傳遞事件(普通事件和自定義事件),由某一後代觸發事件,實現向祖先傳遞消息ui

// grandson
<button @click="sendMsg">觸發祖先的自定義事件</button>
export default {
  methods: {
    sendMsg() {
      this.$listeners['on-send']({ grandson: 'grandson' })
    }
  }
}

// child
<grandson v-on="$listeners"/>

// parent
<child @on-send="receiveMsg" />
export default {
  methods: {
    receiveMsg(param) {
      console.log(param) // { grandson: 'grandson' }
    }
  }
}
複製代碼

兄弟組件傳消息

1. 藉助共同父代或祖先

// brother-send
export default {
  mounted() {
    this.$parent.$emit('parent-msg', { msg: 'msg by parent' })
    this.$root.$emit('root-msg', { msg: 'msg by root' })
  }
}

// brother-receive
export default {
  created() {
    this.$parent.$on('parent-msg', (param) => {
      console.log(param) // { msg: 'msg by parent' }
    })
    this.$root.$on('root-msg', (param) => {
      console.log(param) // { msg: 'msg by root' }
    })
  },
  destroyed() {
    this.$parent.$off('parent-msg')
    this.$root.$off('root-msg')
  }
}

// parent
<div>
  <brother-send />
  <brother-receive />
</div>
複製代碼

無規律跨級通訊

1. 事件總線Bus

能夠直接藉助一個空Vue對象,自帶$on $emit $off的API

// bus.js
export default new Vue()
複製代碼

也能夠本身構造

// bus.js
class Bus {
  constructor() {
    this.callbacks = {}
  }
  $on(name, fn) {
    this.callbacks[name] = this.callbacks[name] || []
    this.callbacks[name].push(fn)
  }
  $emit(name, ...args) {
    if (this.callbacks[name]) {
      this.callbacks[name].forEach(cb => cb(...args))
    }
  }
  $off(name) {
    this.callbacks[name] = null
    Reflect.deleteProperty(this.callbacks, name)
  }
}
export default new Bus()
複製代碼

狀態管理

Vuex

Vuex能解決全部組件之間的通訊問題,但實際上Vuex更像是一個狀態管理的「庫」。Vuex相對比較重,可是能保存全部須要的數據結構,而且全部組件均可以訪問到。是否使用Vuex仍是取決於項目規模,或者說是數據規模。

相關文章
相關標籤/搜索