盘点那些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…