vue兄弟組件之間傳值


  前面說了   

    父組件  >>>>  子組件

    子組件   >>>>  父組件

    父組件  <<<<  子組件

    子組件   <<<<  父組件

相互傳值的方式,那兩個組件不是父子關系咋辦啊?之前面試被問到,問的我一臉懵逼,我當時回答說,localstorage、定義全局變量;

  其實這兩種方式也不是不可以,但老二存了數據進去,老大怎么獲取呢?老大不知道你啥時候存進去了呀!?

  面試結束我就想,移動端開發有廣播,注冊廣播,發送廣播的機制,記得瀏覽器也有這種機制,那是不是vue里邊也有相應的機制呢?

我一搜,哎呦 ~~我去~~ 真有,(妹的,之前也接觸過的,就是通過bus傳遞,沒實際在項目里邊用過,所以忘了)。

  那這個bus具體咋整涅:

1.定義一個單獨的js文件,起名為:vueBus.js,然后里邊寫:

import Vue from 'vue';
let bus = new Vue();
export default bus;

2.在需要接收信息的地方注冊監聽事件:先引入bus

  mounted(){
      let self = this
      bus.$on('fromSecond',(data)=>{
          self.res = data//獲取到傳過來的值
      });
  },

3.然后發送廣播事件:先引入bus

    sendMsg(){
      bus.$emit("fromSecond",this.res)
    }

注意:先引入bus:

import bus from '@/api/vueBus.js'
 
並且發一次,多個注冊過的地方都能接收到
--------------------------------------------------------------------------------------------------------------------------分割線
那實現原理是什么樣的呢?當然知道了上邊的內容完全夠用了,但在這個人人裝b的時代,你不了解原理怎么能夠呢,原理你要知道並且深深的知道!
 
想知道原理就得看源碼:
 
export function eventsMixin (Vue: Class<Component>) {
  const hookRE = /^hook:/
  // 這里是注冊事件
  Vue.prototype.$on = function (event: string | Array<string>, fn: Function): Component {
    const vm: Component = this
    if (Array.isArray(event)) {// 這里看到注冊事件時候可以傳個數組進來
      for (let i = 0, l = event.length; i < l; i++) {//循環着添加事件
        vm.$on(event[i], fn)//調用自己
      }
    } else {// _events是裝所有事件的對象
      // 添加進_events去 如果對應的這個事件名已經有方法了就再往里邊push一個
      // 如果沒有就建一個數組往里邊push
      // 所以 你往數組里邊放幾次執行時候就會執行幾次,
      // 同一個事件名 注冊幾個不同/相同回調方法 都會執行
      (vm._events[event] || (vm._events[event] = [])).push(fn)
      // optimize hook:event cost by using a boolean flag marked at registration
      // instead of a hash lookup
      if (hookRE.test(event)) {
        vm._hasHookEvent = true
      }
    }
    return vm
  }

  // 這里是一次性綁定
  Vue.prototype.$once = function (event: string, fn: Function): Component {
    const vm: Component = this
    // 封裝一個fn 執行時候移除綁定 這樣就實現只能觸發一次了
    function on () {
      vm.$off(event, on)
      fn.apply(vm, arguments)
    }
    on.fn = fn
    vm.$on(event, on)// 綁定封裝過一次的fn
    return vm
  }

  // 移除綁定事件
  Vue.prototype.$off = function (event?: string | Array<string>, fn?: Function): Component {
    const vm: Component = this
    // all
    if (!arguments.length) {
      vm._events = Object.create(null)
      return vm
    }
    // array of events
    // 是數組的話 循環着去解綁
    if (Array.isArray(event)) {
      for (let i = 0, l = event.length; i < l; i++) {
        vm.$off(event[i], fn)
      }
      return vm
    }
    // specific event
    const cbs = vm._events[event]
    if (!cbs) {// 找不到這個事件 你解綁個p呀
      return vm
    }
    if (!fn) {// 解綁時候沒有傳過來 回調方法 你解綁個p呀
      vm._events[event] = null
      return vm
    }
    // specific handler
    let cb
    let i = cbs.length
    while (i--) {
      cb = cbs[i]
      if (cb === fn || cb.fn === fn) {
        cbs.splice(i, 1)//找到他 並且移除他
        break
      }
    }
    return vm
  }

  // 發送事件
  Vue.prototype.$emit = function (event: string): Component {
    const vm: Component = this
    if (process.env.NODE_ENV !== 'production') {
      const lowerCaseEvent = event.toLowerCase()
      if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {
        tip(
          `Event "${lowerCaseEvent}" is emitted in component ` +
          `${formatComponentName(vm)} but the handler is registered for "${event}". ` +
          `Note that HTML attributes are case-insensitive and you cannot use ` +
          `v-on to listen to camelCase events when using in-DOM templates. ` +
          `You should probably use "${hyphenate(event)}" instead of "${event}".`
        )
      }
    }
    // 找到這個方法
    let cbs = vm._events[event]
    if (cbs) {
      cbs = cbs.length > 1 ? toArray(cbs) : cbs

    // 把傳過來的參數去掉第一個,轉化成參數數組
 const args = toArray(arguments, 1) const info = `event handler for "${event}"` for (let i = 0, l = cbs.length; i < l; i++) { // 執行這些方法
 invokeWithErrorHandling(cbs[i], vm, args, vm, info) } } return vm } }

可以看到:添加事件時候會把方法放到Vue的_events對象上,這個對象的key是事件名,value是fn數組;你調用$emit時候,他會根據你傳過來的事件名稱去找到對應的fn數組,循環執行之。

 

看源碼意外收獲:

  1. 注冊事件時候事件名而已傳數組

  2. 一個/組事件名可以綁定不同的方法,執行時候按順序一並執行

  3. 解除事件監聽時候需要傳事件名和方法進來

  4. 注冊一次性事件是怎么完成的

 
over!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM