Vue项目Utils工具包

5,104 阅读3分钟

基于Vue源码设计思想,封装的一套日常开发工具类

gitHub源码地址

在我们日常开发中,每个公司都有自己的工具类,当然封装的方法不同, 有的可能就会放在一个 utils/index.js 文件中, 但是这样存在一个问题就是,如果方法过多的话,维护起来很麻烦,后面就想了一下,对模块进行拆分,常见的比如分为: base、date、file、data、security... 等模块,每个模块做自己对应的方法,如有新增模块,只需要在 utils/index 暴露出去即可, 最后对外界通过index.js 导入使用, 这样实现的功能是一样的,而且维护成本低了很多。

1.目录结构

|-- Utils基本结构
    |-- index.js                             #对外界暴露使用
    |-- install_prototype.js                 #挂载到Vue原型
    |-- README.MD                            #描述文档
    |-- models                               #工具模块
        |-- base.js                          #基本
        |-- data.js                          #数据
        |-- date.js                          #日期
        |-- file.js                          #文件
        |-- security.js                      #安全
        |...

2.安装使用

  1. 由于各个模块中可能有其他依赖,所以建议先 npm i crypto-js 安装依赖;
  2. main.jsimport instalUtils from '@/utils/install_prototype'
  3. 然后再 Vue.use(instalUtils);
  4. 组件中 import { getType } from '@/utils/index';this.$utils.getType()

3.Data模块

/**
 * 存储数据
 * @param {String, Object} key 字段名 
 * @param value 字段值 
 * @return void
 */
export const setStore = (key = "", value) => {
    if (!key) return;
    if (!key instanceof Object) return localStorage.setItem(key, value);
    Object.keys(key).forEach(dataKey => {
        let dataValue = typeof key[dataKey] === 'object' ? JSON.stringify(key[dataKey]) : key[dataKey];
        localStorage.setItem(dataKey, dataValue);
    });
}

/**
 * 获取数据
 * @param {String, Array} key 键名
 * @return {String, Object}
 */
export const getStore = (key = "") => {
    if (typeof key === 'string') return localStorage.getItem(key);
    let dataRes = {};
    key.forEach(dataKey => {
        dataRes[dataKey] = localStorage.getItem(dataKey) || null;
    });
    return dataRes;
}

/**
 * 删除数据
 * @param {String, Array} key 键名
 * @return void
 */
export const deleteStore = (key = "") => {
    let removeKeys = [...key];
    removeKeys.forEach(dataKey => {
        localStorage.removeItem(dataKey);
    });
}

/**
 * 清空Store
 * @return void
 */
export const clearStore = () => {
    localStorage.clear();
}

/**
 * 通过key找到在列表中对应的显示
 * @param {Object} obj
 *  @param obj.dataList 数据列表
 *  @param obj.value    数据的值对应的字段名称   例如 'value'
 *  @param obj.label    数据的说明对应的字段名称 例如 'label'
 *  @param obj.data     当前传入的数据值
 * @return name        返回当前传入值在数组中对应的名字
 */
export const getDataName = obj => {
    let name = obj.data;
    if (Array.isArray(obj.dataList) && obj.dataList.length > 0) {
        for (let i = 0; i < obj.dataList.length; i++) {
            if (obj.dataList[i][obj.value] === obj.data) {
                name = obj.dataList[i][obj.label];
            }
        }
    }
    return name;
}

/**
 * json对象转FormData
 * @param obj
 * @returns {*}
 */
export const jsonToFormData = (obj, oldFormData) => {
    let formData = oldFormData || new FormData();
    if (obj) {
        for (let k in obj) {
            formData.append(k, obj[k]);
        }
    }
    return formData;
}

/**
 * 移除对象中的空字符串
 * @param test
 * @param recurse
 */
export const deleteEmptyString = (test, recurse) => {
    for (let i in test) {
        if (test[i] === '') {
            delete test[i];
        } else if (recurse && typeof test[i] === 'object') {
            deleteEmptyString(test[i], recurse);
        }
    }
}

/**
 * 删除对象中的空Key
 * @param test
 * @param recurse
 */
export const deleteEmptyObject = (test, recurse) => {
    for (let i in test) {
        if (test[i] === undefined || test[i] === null || test[i] === '') {
            delete test[i];
        } else if (recurse && typeof test[i] === 'object') {
            deleteEmptyObject(test[i], recurse);
        }
    }
}

/**
 * 移除对象中的无效属性
 * @param obj
 * @return {*}
 */
export const removeEmpty = obj => {
    Object.keys(obj).forEach(function (key) {
        (obj[key] &&
            typeof obj[key] === 'object' &&
            removeEmpty(obj[key])) ||
        ((obj[key] === undefined || obj[key] === null || obj[key] === '') &&
            delete obj[key]);
    });
    return obj;
}

/**
 * 深度拷贝
 * @param {*} obj
 */
export const deepCloneObject = obj => {
    let objClone = Array.isArray(obj) ? [] : {};
    if (obj && typeof obj === 'object') {
        for (let key in obj) {
            if (obj.hasOwnProperty(key)) {
                //判断ojb子元素是否为对象,如果是,递归复制
                if (obj[key] && typeof obj[key] === 'object') {
                    objClone[key] = deepCloneObject(obj[key]);
                } else {
                    //如果不是,简单复制
                    objClone[key] = obj[key];
                }
            }
        }
    }
    return objClone;
}

/**
 * 获取页面参数
 * @param key 参数名称,不传则返回全部参数
 */
export const getQueryParam = key => {
    let paramValue = '';
    let hash = window.location.hash;
    let paramStr = hash ? (hash.indexOf('?') ? hash.split('?')[1] : '') : '';
    let paramObj = {}; //参数对象
    if (paramStr) {
        paramStr.split('&').forEach(param => {
            let arr = param.split('=');
            let paramKey = arr[0];
            let value = decodeURIComponent(arr[1]);
            paramObj[paramKey] = value;
            if (key && key === paramKey) {
                paramValue = value;
            }
        });
    }

    if (key) return paramValue;
    return paramObj;
}

/**
 * json参数转为query
 * @param Object paramObj  
 * @return String user=1&sex=0
 */
export const paramToQS = paramObj => {
    if (!(paramObj instanceof Object)) return '';
    return Object.keys(paramObj)
        .map(parkey => `${parkey}=${encodeURIComponent(paramObj[parkey])}`)
        .join('&');
}

/**
 * 线性数据转化为树
 * @param {Object} data 源数据
 * @param {Object} parentKey 父级id key
 * @param {childrenKey} childrenKey 子集key
 * @param {Object} pId 父级标识符
 */
export const toTree = (data, parentKey, childrenKey, pId) => {
    let tree = [];
    let temp = null;
    for (let i = 0; i < data.length; i++) {
        if (data[i][parentKey] === pId) {
            let obj = data[i];
            temp = toTree(data, parentKey, childrenKey, data[i][childrenKey]);
            if (temp.length > 0) {
                obj.children = temp;
            }
            tree.push(obj);
        }
    }
    return tree;
}

/**
 * 转换Key
 * @param obj
 * @param keyMap 
 * @param isDeep Boolean 是否深度
 * @return Object/Array
 */
export const convertKey = (obj, keyMap, isDeep) => {
    if (!['[object Array]', '[object Object]'].includes(Object.prototype.toString.call(obj))) {
        throw new TypeError('The first argument should be either an object or an array!');
    }
    if (Object.prototype.toString.call(keyMap) !== '[object Object]') {
        throw new TypeError('The parameter keyMap should be an object!');
    }
    let res = obj instanceof Array ? [] : {};
    if (obj instanceof Object) {
        for (let key in obj) {
            let newKey = Object.keys(keyMap).includes(key) ? keyMap[key] : key;
            res[newKey] = obj[key];

            //是否为深度转换
            if (isDeep && obj[key] instanceof Object && Object.keys(obj[key]).length) {
                res[newKey] = convertKey(obj[key], keyMap, isDeep);
            }
        }
    }
    return res;
}

/**
 * 设置tree层级信息
 * @param {Object} data
 * @param {Object} maxLevel 最多层级
 * @param {Object} currLevel 当前层级,可不传
 */
export const setTreeHierarchyIndex = function (data, maxLevel=10, currLevel) {
    if (!(data instanceof Array)) throw new TypeError('The data should be an array!');
    let result = [];
    for (let k = 0; k < data.length; k++) {
        // console.log('当前层级:', currLevel);
        // console.log('是否在指定层级范围:', currLevel < maxLevel);
        let temp = data[k];
        let newNode = {
            ...temp,
            hierarchyIndex: currLevel + 1,
            children: null
        };
        delete newNode.children;
        //是否在指定层级范围
        if (currLevel >= maxLevel) continue;
        if (temp.children && temp.children.length > 0) {
            currLevel++
            newNode.children = setTreeHierarchyIndex(temp.children, maxLevel, currLevel);
            currLevel--
        }
        result.push(newNode);
    }
    return result;
}

/**
 * 复制数据
 * @param {*}  data
 * @param {Number}  count
 * @return {*}
 */
export const copyData = (data, count = 5) => new Array(count).fill(data);

/**
 * 格式化金钱,每千分位加逗号
 * @param {String} str 
 */
export const formatMoney = (str = "") => {
    if (!str) return "";
    str = str.toString();
    let s = '';
    let count = 0;
    for (let i = str.length - 1; i >= 0; i--) {
        count++
        s = str[i] + s
        if (count % 3 == 0 && i != 0) s = ',' + s;
    }
    return s
}

/**
 * 扁平化数组
 * @param {Array} arr 
 * @returns {Array}
 */
export const flatArr = (arr=[]) => {
    return arr.reduce((item, next) => item.concat(Array.isArray(next) ? flatArr(next) : next, []), []);
}

/**
 * 是否为json
 * @param {*} data 
 * @returns {Boolean}
 */
export const isJson = (data=null) => {
    try {
        if (typeof data !== 'string') return false;
        let jsonObj = JSON.parse(data);
        return !!(jsonObj && typeof jsonObj === 'object');
    } catch (error) {
        console.log(error);
        return false;
    }
}

/**
 * 删除array/obj中的Key
 * @param {Array|Object} data 
 * @param {Array} keys 
 * @returns {Array|Object}
 */
const deleteMapKey = (data = null, keys = null) => {
    keys = keys instanceof Array ? keys : keys ? [keys] : keys;
    const dataType = Object.prototype.toString.call(data).slice(8, -1).toLowerCase();
    if (!['array', 'object'].includes(dataType) || !(keys instanceof Array)) return data;
    
    //生成新的Map
    let genNewMap = (obj, diskeys) => {
        Object.keys(obj).forEach(key => {
            keys.includes(key) && delete obj[key];
        });
        return obj;
    }

    //array or obj
    if (dataType === 'array') {
        return data.map(item => (typeof item === 'object' ? genNewMap(item, keys) : item));
    } else {
        return genNewMap(data, keys);
    }
}

4.注意事项

  1. 本工具类 Vue 项目可以拿来直接使用,如果是React或其他项目,需要挂载到原型的话需要更改install_prototype.js 这个文件;

  2. 为了风格统一,请使用 import {fn1, fn2, fn3, ...fnx} from '@/utils' 方式使用;


更多方法持续更新中...