vue中的一些工具方法
- 类型判断
/**
* Get the raw type string of a value, e.g., [object Object].
*/
const _toString = Object.prototype.toString
export function toRawType (value: any): string {
return _toString.call(value).slice(8, -1)
}
- 生成字符串
/**
* Convert a value to a string that is actually rendered.
*/
export function toString {
return val == null
? ''
: Array.isArray(val) || (toRawType(val)==='Object' && val.toString === _toString)
? JSON.stringify(val, null, 2) // 粗略的将引用类型转换为 JSON
: String(val) // 粗略的将 基本类型 值 转换成 字符串
}
3.创建一个缓存机制的函数
/**
* Create a cached version of a pure function.
*
* 面试经常会面到的方法: 生成带有缓存的 函数 ( 闭包的应用 )
*/
export function cached() {
const cache = Object.create(null)
return (function cachedFn () {
const hit = cache[str] // 如果已缓存, hit 就是有数据的, 如果为缓存 hit 就是 undefined
return hit || (cache[str] = fn(str))
})
}
4.a-b
转驼峰aB
/**
* Camelize a hyphen-delimited string.
*/
const camelizeRE = /-(\w)/g
export const camelize = cached((str: string): string => {
return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : '')
})
- 驼峰
aB
转a-b
/**
* Hyphenate a camelCase string.
*/
const hyphenateRE = /\B([A-Z])/g
export const hyphenate = cached(() => {
return str.replace(hyphenateRE, '-$1').toLowerCase()
})
- 判断两个值是否相等;包括引用类型
// 在面试中可能会遇到, 思想重要
// 比较两个对象是否是相等的 两个对象
// 1. js 中对象是无法使用 == 来比较的, 比是地址
// 2. 我们一般会定义如果对象的各个属性值都相等 那么对象就是相等的对象. 例如: {} 就与 {} 相等.
// 算法描述
// 1. 假定对象 a 和 b
// 2. 遍历 a 中的成员, 判断是否每一个 a 中的成员都在 b 中. 并且 与 b 中的对应成员相等.
// 3. 再遍历 b 中的成员, 判断是否每一个 b 中的成员都在 a 中. 并且 与 a 中的对应成员相等.
// 4. 如果成员是引用类型, 递归.
// 抽象一下, 判断两个集合是否相等
/**
* Check if two values are loosely equal - that is,
* if they are plain objects, do they have the same shape?
*/
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]) // b 包含 a
})
} else if (a instanceof Date && b instanceof Date) {
return a.getTime() === b.getTime() // 单独处理 Date 类型, 时间戳应该是一样的
} else if ( 0 ) {
// 如果需要考虑其它类型, 添加 if 即可
} else if (!isArrayA && !isArrayB) {
const keysA = Object.keys(a)
const keysB = Object.keys(b)
// 先判断 key 的长度, 再判断 a 包含于 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 中有函数方法 ( on, off 等, once ), once 事件就是这个思路
/**
* 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模版中使用
user.userInfo.userName
,是如何找到对应的值;
// 分析
// 通过对. 进行分割得到一个类似于['xxx','yyy','zzz']的数组,然后对其进行遍历
let res = null;
res = obj[path[0]];
res = res[path[1]];
res = res[path[2]];
以此规律...
let getValueByPath = (obj,pathStr)=>{
let pathArr = pathStr.split('.');
let result = obj,pop;
while(pop = pathArr.shift()){
result = result[pop];
}
return result;
}
// 利用函数柯理化进行优化
let createGetValueByPath = (pathStr)=>{
let pathArr = pathStr.split('.');
return getValueByPath=(obj)=>{
let result = obj,pop;
while(pop = pathArr.shift()){
result = result[pop];
}
return result;
}
}
- 利用函数柯里化进行tag判断是否为html标签
var isHTMLTag = makeMap(
'html,body,base,head,link,meta,style,title,' +
'address,article,aside,footer,header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,' +
'div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul,' +
'a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,' +
's,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,' +
'embed,object,param,source,canvas,script,noscript,del,ins,' +
'caption,col,colgroup,table,thead,tbody,td,th,tr,' +
'button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,' +
'output,progress,select,textarea,' +
'details,dialog,menu,menuitem,summary,' +
'content,element,shadow,template,blockquote,iframe,tfoot'
);
function makeMap (
str,
expectsLowerCase
) {
var map = Object.create(null);
var list = str.split(',');
for (var i = 0; i < list.length; i++) {
map[list[i]] = true;
}
return expectsLowerCase
? function (val) { return !!map[val.toLowerCase()]; }
: function (val) { return !!map[val]; }
}
//这样能够大大的提高了匹配的效率以及性能