盘点那些vue源码中的实用函数

611 阅读2分钟

盘点那些vue源码中的实用函数

1. 缓存函数

export function function cache(fn) {
  const cache = Object.create(null)
  return ( function cachedFn(str) {
    const hit = cache[str]
    return hit || (cache[str] = fn(str))
  })
}

这是一个缓存函数的方法,其中vuex的缓存来自于此函数,目前笔者用这个函数来进行请求的缓存(不经常更新的数据,组织架构等)

2. 原生bind的兼容性写法

function polyfillBind (fn: Function, ctx: Object): Function {
  function boundFn (a) {
    const l = arguments.length
    return l
      ? l > 1
        ? fn.apply(ctx, arguments)
        : fn.call(ctx, a)
      : fn.call(ctx)
  }

  boundFn._length = fn.length
  return boundFn
}

主要是为了兼容不同浏览器的bind 函数的写法,当浏览器的宿主环境不支持时可以实用此方法,模拟原生函数的bind方法。

3. 伪数组转真数组的方法

export function toArray (list: any, start?: number): Array<any> {
  start = start || 0
  let i = list.length - start
  const ret: Array<any> = new Array(i)
  while (i--) {
    ret[i] = list[i + start]
  }
  return ret
}

该方法的主要目的是为了给类似dom对象的伪数组增加数组的方法, 在vue中 的使用场景是在组件install 时需要给组件进行注册代码如下。

import { toArray } from '../util/index'

export function initUse (Vue: GlobalAPI) {
  Vue.use = function (plugin: Function | Object) {
    const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
    if (installedPlugins.indexOf(plugin) > -1) {
      return this
    }

    // additional parameters
    const args = toArray(arguments, 1)
    args.unshift(this)
    if (typeof plugin.install === 'function') {
      plugin.install.apply(plugin, args)
    } else if (typeof plugin === 'function') {
      plugin.apply(null, args)
    }
    installedPlugins.push(plugin)
    return this
  }
}

4. 代码混入

/**
 * Mix properties into target object.
 */
export function extend (to: Object, _from: ?Object): Object {
  for (const key in _from) {
    to[key] = _from[key]
  }
  return to
}

/**
 * Merge an Array of Objects into a single Object.
 */
export function toObject (arr: Array<any>): Object {
  const res = {}
  for (let i = 0; i < arr.length; i++) {
    if (arr[i]) {
      extend(res, arr[i])
    }
  }
  return res
}

此方法主要是将对象的方法混入到一个新的对象中,此方法在vue中常见是封装自定义方法事件,keycode时会使用,当然vue中的使用场景也与此类似,我们常用的extend方法也来源与此,其实也包含webpack-merge 也是使用的同样的方法

5. 判断对象是否全等的方法

export function looseEqual (a: any, b: any): boolean {
  if (a === b) return true
  const isObjectA = isObject(a)
  const isObjectB = isObject(b)
  if (isObjectA && isObjectB) {
    try {
      const isArrayA = Array.isArray(a)
      const isArrayB = Array.isArray(b)
      if (isArrayA && isArrayB) {
        return a.length === b.length && a.every((e, i) => {
          return looseEqual(e, b[i])
        })
      } else if (a instanceof Date && b instanceof Date) {
        return a.getTime() === b.getTime()
      } else if (!isArrayA && !isArrayB) {
        const keysA = Object.keys(a)
        const keysB = Object.keys(b)
        return keysA.length === keysB.length && keysA.every(key => {
          return looseEqual(a[key], b[key])
        })
      } else {
        /* istanbul ignore next */
        return false
      }
    } catch (e) {
      /* istanbul ignore next */
      return false
    }
  } else if (!isObjectA && !isObjectB) {
    return String(a) === String(b)
  } else {
    return false
  }
}

字面意思不需要解释,主要是为了判断两个对象是否全等。在vue中常用在判断两个vdom 是否相等。

6. 只需要执行一次的函数

/**
 * Ensure a function is called only once.
 */
export function once (fn: Function): Function {
  let called = false
  return function () {
    if (!called) {
      called = true
      fn.apply(this, arguments)
    }
  }
}

目前的使用场景可以预见的是某些支付场景,只允许点击一次,在vue中基本上也是用在$once 中。另外贴一个连接,关于vue中的事件的描述。blog.csdn.net/xiaodi52052…