hot-form
Version:
A project developed based on ant-design-vue and vant whitch do some things on create/render/modify and etc. for forms. Also can custom some component on the form items if you want. 一个基于antdv/vant开发的创建表单组件,包含表单渲染、表单编辑页面、以及植入自定义附加内容的组件
146 lines (134 loc) • 4.83 kB
JavaScript
/**
* 对象深度复制,注: 不支持 Map | Set 等类似数据类型
* @param {Object} obj - 原始数据
* @returns {Object} - 复制后的数据
*/
export function deepClone(obj) {
// 排除函数/正则/日期
if (obj instanceof Function || obj instanceof RegExp || obj instanceof Date) return obj;
const clone = Object.assign({}, obj);
Object.keys(clone).forEach(key => (clone[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]));
return Array.isArray(obj) && obj.length
? (clone.length = obj.length) && Array.from(clone)
: Array.isArray(obj)
? Array.from(obj)
: clone;
}
// 数组去重
export function unique(arr) {
return Array.from(new Set([].concat(arr)));
}
/** 是否是引用类型 (Note: 包含数组) */
export const isObject = val => val !== null && typeof val === 'object';
/**
* 对象深度冻结,会修改原数据,注: 不支持 Map | Set 等类似数据类型
* @param {Object} obj 需要冻结的数据
* @returns {Object} 冻结后的数据
*/
export function deepFreeze(obj) {
if (isObject(obj) && !Object.isFrozen(obj)) {
Object.freeze(obj);
Object.keys(obj).forEach(property => deepFreeze(obj[property]));
}
return obj;
}
/**
* 给对象添加属性
* @param {*} target 目标对象
* @param {*} property 属性
* @param {*} value 属性值
*/
export function defineReadonly(target, property, value) {
Object.defineProperty(target, property, {
configurable: false,
enumerable: true,
writable: false,
value,
});
}
export function getBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
});
}
/**
* 遍历树形结构,修改属性名
* @param {Function} transfer - 想要得到的数据结构的函数
* @param {Array} data - 树形结构数据
* @param {String} oldChildName - 原数据中需要递归的属性名
* @param {String} newChildName - 得到数据需要递归想要的属性名
* @returns {Array} - 返回处理(改属性名)之后的数组
*/
export function walkerTree(transfer, data = [], oldChildName = 'children', newChildName = 'children') {
return data.map(({ [oldChildName]: children = [], ...node }) => {
const newNode = transfer(node, data);
if (Array.isArray(children) && children.length) newNode[newChildName] = walkerTree(transfer, children, oldChildName, newChildName);
return newNode;
});
}
/**
* 扁平树结构
* @param {*} walker - 返回的数据项结构
* @param {*} data - 源数据
* @param {*} parent - 父级结构
* @param {*} childName - 树形的下级结构的属性名,默认children
* @param {*} level 当前遍历深度
* @returns {Array} - 返回去扁平化处理的数组结构
*/
export function flatTree(walker, data = [], parent, childName = 'children', level = 1) {
return data.reduce((prev, cur) => {
const value = walker(cur, parent, level);
prev.push(value);
if (Array.isArray(cur[childName]) && cur[childName].length) {
prev.push(...flatTree(walker, cur[childName], value, childName, level + 1))
}
return prev;
}, []);
}
/**
* 构建树结构
* @param {Function} decider - 子节点与父节点的链接条件
* @param {*} data - 树形结构扁平化之后的数组
* @param {*} parent - 顶级结点标志
*/
export function createTree(decider, data, parent) {
const [list, rest] = collector(decider, data, parent);
if (!rest.length) return list;
return list.map(({ ...item }) => {
const children = createTree(decider, rest, item);
if (children.length) item.children = children;
return item;
});
}
/**
* 分离出父级结点和其他子结点
* @param {Function} decider - 子节点与父节点的链接条件
* @param {*} data - 树形结构扁平化之后的数组
* @param {*} parent - 父级结点
*/
const collector = (decider, data, parent) =>
data.reduce(
(arr, item) => {
const bool = decider(item, parent);
arr[+!bool].push(item);
return arr;
},
[[], []]
);
/**
* 转换成对象类型
* 将数组对象中传入的 `label` 键的值作为键,
* 传入的 `value` 键的值作为值组成一个新的对象
* @param {Object Array|readonly<Object Array>} arr
* @param {String | Number} label
* @param {String | Number} value
* @return {Object} 键名为 label,值为 value
*/
export function toNameMap(arr = [], label = 'label', value = 'value') {
return arr.reduce((prev, cur) => {
return { ...prev, [cur[label]] : value ? cur[value] : '' };
}, {});
}