@alifd/next
Version:
A configurable component library for web built on React.
311 lines (310 loc) • 9.92 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.values = exports.isReactFragmentElement = exports.isForwardRefComponent = exports.isClassComponent = exports.isFunctionComponent = exports.deepMerge = exports.isNil = exports.pickAttrsWith = exports.pickProps = exports.pickOthers = exports.each = exports.shallowEqual = exports.isPlainObject = exports.isPromise = exports.isArrayLike = exports.typeOf = void 0;
var tslib_1 = require("tslib");
var react_1 = tslib_1.__importDefault(require("react"));
/**
* 获取对象的类型
* @example
* typeOf([]) === 'Array'
* typeOf() === 'Undefined'
* typeOf(1) === 'Number'
*/
function typeOf(obj) {
return Object.prototype.toString.call(obj).replace(/\[object\s|]/g, '');
}
exports.typeOf = typeOf;
/**
* 判断是否是数组或类数组对象
* @example
* isArrayLike([]) === true
* isArrayLike(arguments) === true
* isArrayLike(this.props.children) === true
*/
function isArrayLike(obj) {
if (!obj || typeof obj !== 'object') {
return false;
}
var length = !!obj && 'length' in obj && obj.length;
var type = typeOf(obj);
return (type === 'Array' ||
length === 0 ||
(typeof length === 'number' && length > 0 && length - 1 in obj));
}
exports.isArrayLike = isArrayLike;
/**
* 判断对象是否是一个 promise,即是否可以用.then
*/
function isPromise(obj) {
return (!!obj &&
(typeof obj === 'object' || typeof obj === 'function') &&
typeof obj.then === 'function');
}
exports.isPromise = isPromise;
/**
* 是否是一个纯净的对象
* @see https://github.com/jonschlinkert/is-plain-object
*/
function isPlainObject(obj) {
if (typeOf(obj) !== 'Object') {
return false;
}
var ctor = obj.constructor;
if (typeof ctor !== 'function') {
return false;
}
var prot = ctor.prototype;
if (typeOf(prot) !== 'Object') {
return false;
}
if (!prot.hasOwnProperty('isPrototypeOf')) {
return false;
}
return true;
}
exports.isPlainObject = isPlainObject;
/**
* 对象浅比较
* @example
* object.shallowEqual(\{a: 100\}, \{a: 100\}); // true
*/
function shallowEqual(objA, objB, compare) {
if (objA === objB) {
return true;
}
// 其中一个不是 object,则不相等
if (!objA || !objB || typeof objA + typeof objB !== 'objectobject') {
return false;
}
var keyA = Object.keys(objA);
var keyB = Object.keys(objB);
var len = keyA.length;
// key 数量不一致则不相等
if (len !== keyB.length) {
return false;
}
var hasCallback = typeof compare === 'function';
for (var i = 0; i < len; i++) {
var key = keyA[i];
if (!Object.prototype.hasOwnProperty.call(objB, key)) {
return false;
}
var valA = objA[key];
var valB = objB[key];
var ret = hasCallback ? compare(valA, valB, key) : void 0;
if (ret === false || (ret === void 0 && valA !== valB)) {
return false;
}
}
return true;
}
exports.shallowEqual = shallowEqual;
/**
* 遍历对象或数组,或者类数组,例如 React 中的 children 对象、arguments 等
* @param obj - 目标对象或类数组
* @param callback - fn(n, i) or fn(val, key)
* @param direction - 是否倒序遍历,只对数组有效,传入 -1 则是倒序
*
* @example
* // 遍历数组
* object.each([100, 200, 300], (n, i) =\> console.log(n, i));
* // 遍历json对象
* object.each(\{a: 100, b: 200\}, (value, key) =\> console.log(key, value));
* // 遍历React子节点
* object.each(this.props.children, (child, index) =\> console.log(child));
* // 遍历arguments
* object.each(arguments, (arg, i) =\> console.log(arg));
*/
function each(obj, callback, direction) {
var reversed = direction === -1;
if (isArrayLike(obj)) {
var length_1 = obj.length;
for (var i = reversed ? length_1 - 1 : 0; i < length_1 && i >= 0; reversed ? i-- : i++) {
var shouldContinue = callback.call(obj[i], obj[i], i);
if (shouldContinue === false) {
break;
}
}
}
else {
for (var key in obj) {
/* istanbul ignore else */
if (obj.hasOwnProperty(key)) {
var shouldContinue = callback.call(obj[key], obj[key], key);
if (shouldContinue === false) {
break;
}
}
}
}
return obj;
}
exports.each = each;
// @private 判断 key 是否在数组或对象中
var _isInObj = function (key, obj, isArray) {
return isArray ? obj.indexOf(key) > -1 : key in obj;
};
/**
* 过滤出其它属性
* @param holdProps - 过滤的参照对象,最终的结果只保留不在参照对象中的 key
* @param props - 被过滤的对象
*
* @example
* object.pickOthers(FooComponent.propTypes, this.props);
* object.pickOthers(['className', 'onChange'], this.props);
*/
function pickOthers(holdProps, props) {
var others = {};
var isArray = typeOf(holdProps) === 'Array';
for (var key in props) {
if (!_isInObj(key, holdProps, isArray)) {
others[key] = props[key];
}
}
return others;
}
exports.pickOthers = pickOthers;
/**
* 过滤出需要的属性
* @param holdProps - 过滤的参照对象,最终的结果只保留在参照对象中的 key
* @param props - 被过滤的对象
*
* @example
* object.pickProps(FooComponent.propTypes, this.props);
* object.pickProps(['className', 'onChange'], this.props);
*/
function pickProps(holdProps, props) {
var others = {};
var isArray = typeOf(holdProps) === 'Array';
for (var key in props) {
if (_isInObj(key, holdProps, isArray)) {
others[key] = props[key];
}
}
return others;
}
exports.pickProps = pickProps;
/**
* 过滤出带 prefix 的属性
* @param holdProps - 过滤的参照对象,最终的结果只保留不在参照对象中的 key
* @param prefix - 包含的字符串
*
* @example
* object.pickAttrsWith(FooComponent.propTypes, 'data-');
*/
function pickAttrsWith(holdProps, prefix) {
var others = {};
for (var key in holdProps) {
if (key.match(prefix)) {
others[key] = holdProps[key];
}
}
return others;
}
exports.pickAttrsWith = pickAttrsWith;
/**
* Checks if value is `null` or `undefined`.
*/
function isNil(value) {
// It will returns `true` only if `null` or `undefined` compare with `null`
// with loose equaliy
return value == null; // eslint-disable-line eqeqeq
}
exports.isNil = isNil;
/**
* Deep merge two objects.
* @see https://stackoverflow.com/questions/27936772/how-to-deep-merge-instead-of-shallow-merge?page=1&tab=votes#tab-top
*/
function deepMerge(target) {
var _a, _b;
var sources = [];
for (var _i = 1; _i < arguments.length; _i++) {
sources[_i - 1] = arguments[_i];
}
if (!sources.length)
return target;
var source = sources.shift();
if (!isPlainObject(target)) {
target = {};
}
if (isPlainObject(target) && isPlainObject(source)) {
for (var key in source) {
// 如果是 object 进行深拷贝
if (isPlainObject(source[key]) && !react_1.default.isValidElement(source[key])) {
if (!target[key])
Object.assign(target, (_a = {}, _a[key] = {}, _a));
// fix {a: 'te'}, {a:{b:3}}
if (!isPlainObject(target[key])) {
target[key] = source[key];
}
deepMerge(target[key], source[key]);
// string/number/function/react node 等直接复制
}
else {
Object.assign(target, (_b = {}, _b[key] = source[key], _b));
}
}
}
return deepMerge.apply(void 0, tslib_1.__spreadArray([target], tslib_1.__read(sources), false));
}
exports.deepMerge = deepMerge;
/**
* 组件是否为 Fucntion Component
* @param component - 传入的组件
*/
function isFunctionComponent(component) {
return (typeOf(component) === 'Function' &&
component.prototype &&
component.prototype.isReactComponent === undefined);
}
exports.isFunctionComponent = isFunctionComponent;
/**
* 组件是否为 Class Component
* @param component - 传入的组件
*/
function isClassComponent(component) {
return (typeOf(component) === 'Function' &&
component.prototype &&
component.prototype.isReactComponent !== undefined);
}
exports.isClassComponent = isClassComponent;
function isForwardRefComponent(component) {
if (!component || typeof component !== 'object') {
return false;
}
var $$typeof = component.$$typeof;
// FIXME 依据 react 内部实现代码来判断,有可能因 react 版本变更错误判断,先用测试用例来保证运行正常,关注测试用例异常适时调整此处代码
return (!!$$typeof && $$typeof.toString().includes('react.forward_ref')) || $$typeof === 0xead0;
}
exports.isForwardRefComponent = isForwardRefComponent;
/**
* 判断是否为 isReactFragmentElement
* @param component - 传入的组件
*/
function isReactFragmentElement(component) {
if (isNil(component)) {
return false;
}
var type = component.type;
return type === react_1.default.Fragment;
}
exports.isReactFragmentElement = isReactFragmentElement;
/**
* Creates an array of the own enumerable string keyed property values of object.
* @example
* // returns [1, 2]
* values(\{a: 1, b: 2\})
*/
function values(obj) {
if (Object.values) {
return Object.values(obj);
}
var vals = [];
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
vals.push(obj[key]);
}
}
return vals;
}
exports.values = values;
;