公用工具方法 (src/shared/util.js)
emptyObject
/** 冻结{}对象 */
export const emptyObject = Object.freeze({});
isUndef、isDef、isTrue、isFalse
/** 是否未被定义,如果参数等于undefined或者为空,返回true */
export function isUndef(v) {
return v === undefined || v === null;
}
/** 是否定义,如果参数不等于undefined或者为空,返回true */
export function isDef(v) {
return v !== undefined && v !== null;
}
/** 是否真,参数为真时返回true */
export function isTrue(v) {
return v === true;
}
/** 是否假,参数为假时返回true */
export function isFalse(v) {
return v === false;
}
isPrimitive
/** 监测value类型是否为 string、number、symbol、boolean */
export function isPrimitive(value) {
return (
typeof value === 'string' ||
typeof value === 'number' ||
typeof value === 'symbol' ||
typeof value === 'boolean'
);
}
isObject
/** 是否为对象,如果对象不等于空且typeof返回为object,返回true */
export function isObject(obj) {
return obj !== null && typeof obj === 'object';
}
_toString、toRawType、isPlainObject、isRegExp
/** 该方法返回描述某个对象数据类型的字符串,
* 如自定义的对象没有被覆盖,则会返回“[object type]”,
* 其中,type则是实际的对象类型。在使用该方法检测的时候,
* 可以使用Object.prototype.toString.call()
* 或者Object.prototype.toString.apply()进行测试 */
var _toString = Object.prototype.toString;
/** 返回value的类型 */
export function toRawType(value) {
return _toString.call(value).slice(8, -1);
}
/** 判断指定参数是否是一个纯粹的对象 */
export function isPlainObject(obj) {
return _toString.call(obj) === '[object Object]';
}
/** 是否是正则表达式 */
export function isRegExp(v) {
return _toString.call(v) === '[object RegExp]';
}
isValidArrayIndex
/** 检查val是否是有效的数组索引值 */
export function isValidArrayIndex(val) {
var n = parseFloat(String(val));
return n >= 0 && Math.floor(n) === n && isFinite(val);
}
isPromise
/** val 是否是Promise函数 */
export function isPromise(val) {
return isDef(val) && typeof val.then === 'function' && typeof val.catch === 'function';
}
toString、toNumber
/** 将val转换为实际呈现的字符串 */
export function toString(val) {
let result;
if (val == null) {
result = '';
} else {
if (Array.isArray(val) || (isPlainObject(val) && val.toString === _toString)) {
result = JSON.stringify(val, null, 2);
} else {
result = String(val);
}
}
return result;
// return val == null
// ? ''
// : Array.isArray(val) || (isPlainObject(val) && val.toString === _toString)
// ? JSON.stringify(val, null, 2)
// : String(val);
}
/** 将val转换为数字,否则返回val本身 */
export function toNumber(val) {
var n = parseFloat(val);
return isNaN(n) ? val : n;
}
makeMap、isBuiltInTag、isReservedAttribute
/**
* 缓存一个键值对map, 返回一个检查val是否在这个键值对的函数(柯里化)
* @param {*} str 用于缓存键值对的字符串
* @param {*} expectsLowerCase 是否将返回函数的参数小写化
*/
export 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];
};
}
/**检查一个标签是否是 slot 或者 component
* @param {*} val 要检查的标签名(函数内处理时将val小写化)
*/
export var isBuiltInTag = makeMap('slot,component', true);
/**检查属性是否是保留属性(key,ref,slot,slot-scope,is)
* @param {*} val 要检查的属性名
*/
export var isReservedAttribute = makeMap('key,ref,slot,slot-scope,is');
remove
/** 从数组arr中删除第一个出现的item */
export function remove(arr, item) {
if (arr.length) {
var index = arr.indexOf(item);
if (index > -1) {
return arr.splice(index, 1);
}
}
}
hasOwn
var hasOwnProperty = Object.prototype.hasOwnProperty;
/** 检查obj是否具有key对应的属性 */
export function hasOwn(obj, key) {
return hasOwnProperty.call(obj, key);
}
cached、camelize、capitalize、hyphenate
/** 创建纯函数的缓存。(柯里化) */
export function cached(fn) {
var cache = Object.create(null);
return function cachedFn(str) {
return cache[str] || (cache[str] = fn(str));
};
}
/** 将 str 驼峰化 */
export var camelize = cached(function (str) {
return str.replace(/-(\w)/g, function (_, c) {
return c ? c.toUpperCase() : '';
});
});
/** 将 str 首字母大写 */
export var capitalize = cached(function (str) {
return str.charAt(0).toUpperCase() + str.slice(1);
});
const hyphenateRE = /\B([A-Z])/g;
/** 将驼峰 str 转换为 - 字符 */
export var hyphenate = cached(function (str) {
return str.replace(/\B([A-Z])/g, '-$1').toLowerCase();
});
polyfillBind、nativeBind
/** bind方法的polyfill(为了兼容性) */
function polyfillBind(fn, ctx) {
function boundFn(a) {
var l = arguments.length;
let result;
if (l > 1) result = fn.apply(ctx, arguments);
else if (l === 1) result = fn.call(ctx, a);
else result = fn.call(ctx);
return result;
}
boundFn._length = fn.length;
return boundFn;
}
function nativeBind(fn, ctx) {
return fn.bind(ctx);
}
/** 判定函数bind是原生的还是polyfill */
export var bind = Function.prototype.bind ? nativeBind : polyfillBind;
toArray
/**
* 将类数组转换为真正的数组
* @param {*} list 要转换的类数组
* @param {*} start 开始位置
*/
export function toArray(list, start) {
start = start || 0;
var i = list.length - start;
var ret = new Array(i);
while (i--) {
ret[i] = list[i + start];
}
return ret;
}
extend
/** 将 _from 中的属性混合到 to中 */
export function extend(to, _from) {
for (var key in _from) {
to[key] = _from[key];
}
return to;
}
toObject
/**将对象数组合并为单个对象 */
export function toObject(arr) {
var res = {};
for (var i = 0; i < arr.length; i++) {
if (arr[i]) {
extend(res, arr[i]);
}
}
return res;
}
noop、no、identify
/** 应该是为了Flow类型检测用的代码 */
export function noop(a, b, c) {}
/** 始终返回 false */
export var no = function (a, b, c) {
return false;
};
/** 传入什么返回什么 */
export var identity = function (_) {
return _;
};
genStaticKeys
/** 从编译器模块生成包含静态键的字符串,
* 将 modules 数组每个元素的 staticKeys 用","拼接起来
*/
export function genStaticKeys(modules) {
return modules
.reduce(function (keys, m) {
return keys.concat(m.staticKeys || []);
}, [])
.join(',');
}
looseEqual、looseIndexOf
/** 判断两个参数是否相等,也可以判断数组和对象是否相等 */
export function looseEqual(a, b) {
//如果:参数a和参数b恒等于返回true;
if (a === b) {
return true;
}
var isObjectA = isObject(a);
var isObjectB = isObject(b);
if (isObjectA && isObjectB) {
try {
var isArrayA = Array.isArray(a);
var isArrayB = Array.isArray(b);
if (isArrayA && isArrayB) {
//a和b为数组,且元素相同
return (
a.length === b.length &&
a.every(function (e, i) {
return looseEqual(e, b[i]);
})
);
} else if (a instanceof Date && b instanceof Date) {
return a.getTime() === b.getTime();
} else if (!isArrayA && !isArrayB) {
// a和b是否为普通对象,且键值相同
var keysA = Object.keys(a);
var keysB = Object.keys(b);
return (
keysA.length === keysB.length &&
keysA.every(function (key) {
return looseEqual(a[key], b[key]);
})
);
} else {
return false;
}
} catch (e) {
return false;
}
} else if (!isObjectA && !isObjectB) {
return String(a) === String(b);
} else {
return false;
}
}
/** 返回arr数组中值等于val的第一个元素的下标 */
export function looseIndexOf(arr, val) {
for (var i = 0; i < arr.length; i++) {
if (looseEqual(arr[i], val)) {
return i;
}
}
return -1;
}