<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Vue 源碼解析 (四)初始化事件流程

          共 8605字,需瀏覽 18分鐘

           ·

          2021-05-08 19:52

          Vue 源碼解析 (四)初始化事件流程

          initEvents

          • vm 出現(xiàn) _events 對(duì)象
          • vm 出現(xiàn) _hasHookEvent 表示是否存在 hook 事件
          • 初始化 updateComponentListeners
          export function initEvents (vm: Component{
            vm._events = Object.create(null)
            vm._hasHookEvent = false
            // init parent attached events
            const listeners = vm.$options._parentListeners
            if (listeners) {
              updateComponentListeners(vm, listeners)
            }
          }

          add

          添加事件,內(nèi)部使用 $on 監(jiān)聽(tīng)綁定事件

          function add (event, fn{
            target.$on(event, fn)
          }

          remove

          解綁事件,內(nèi)部使用 $off 解綁事件

          function remove (event, fn{
            target.$off(event, fn)
          }

          createOnceHandler

          創(chuàng)建只執(zhí)行一次的 once 事件,返回一個(gè)函數(shù)體

          function createOnceHandler (event, fn{
            const _target = target
            return function onceHandler ({
              const res = fn.apply(nullarguments)
              if (res !== null) {
                _target.$off(event, onceHandler)
              }
            }
          }

          updateComponentListeners

          • 更新前 target = vm
          • 更新事件
          • 更新后 target = null
          export function updateComponentListeners (
            vm: Component,
            listeners: Object,
            oldListeners: ?Object
          {
            target = vm
            updateListeners(listeners, oldListeners || {}, add, remove, createOnceHandler, vm)
            target = undefined
          }

          eventsMixin

          Vue.prototype.$on

          • 判斷要監(jiān)聽(tīng)的事件是不是數(shù)組,如果是,逐個(gè)監(jiān)聽(tīng)
          • 否則,vm._events 保存事件
          • 檢測(cè)到魔板存在 hook 事件,則把 _hasHookEvent 設(shè)置為 true
          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 {
                (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
            }

          以下代碼會(huì)執(zhí)行上面的代碼:

          <keep-alive>
             <comp-a @hook:updated="hookUpdated"           @hook:mounted="hookUpdated" />
          </keep-alive>

          Vue.prototype.$once

          不知道這個(gè)事件是干嘛用的

          Vue.prototype.$once = function (event: string, fn: Function): Component {
              const vm: Component = this
              function on ({
                vm.$off(event, on)
                fn.apply(vm, arguments)
              }
              on.fn = fn
              vm.$on(event, on)
              return vm
            }

          Vue.prototype.$off

          用于解綁事件監(jiān)聽(tīng)

          • 判斷參數(shù)是否存在,不存在直接返回
          • 判斷事件參數(shù)是不是數(shù)組,逐個(gè)解綁事件

            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) {
                return vm
              }
              if (!fn) {
                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
            }

          ue.prototype.$emit

          事件派發(fā)

           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(arguments1)
                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
            }

          從源碼閱讀過(guò)程中,我還發(fā)現(xiàn) hook 可以這樣寫:

          beforeCreate: [
                              function a(console.log("beforeCreate")},
                              function b(console.log("beforeCreate")}
          ],


          瀏覽 35
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产Avaaa | 污网站在线观看 | 嫩草网址| 人人看人人射 | 国产成人无码精品亚洲 |