工具函数

220 阅读3分钟

空对象判断({})

function isEmptyObject(value) {
  return value && Object.keys(value).length === 0 && value.constructor === Object;
}

websocket

import { socket_url } from '@/config/query'

var ws;//websocket实例
var lockReconnect = false;//避免重复连接

function parse(v, h) {
  let msg = JSON.parse(v);
  typeof h === 'function' && h(msg);
}

function createWebSocket(url, handle) {
  try {
    ws = new WebSocket(url);
    initEventHandle(url, handle);
  } catch (e) {
    reconnect(url, handle);
  }
}

function initEventHandle(wsUrl, handle) {
  ws.onclose = function (evnt) {
    //console.log('websocket服务关闭了');
    reconnect(wsUrl, handle);
  };
  ws.onerror = function (evnt) {
    //console.log('websocket服务出错了');
    reconnect(wsUrl, handle);
  };
  ws.onopen = function (evnt) {
    //心跳检测重置
    heartCheck.reset().start();
  };
  ws.onmessage = function (evnt) {
    //如果获取到消息,心跳检测重置
    //拿到任何消息都说明当前连接是正常的
    //console.log('websocket服务获得数据了');

    //接受消息后的UI变化
    if (evnt.data && evnt.data[0] === "{") doWithMsg(evnt.data, handle);
    heartCheck.reset().start();
  }

  //收到消息推送
  function doWithMsg(msg, handle) {
    parse(msg, handle)
  }
}

function reconnect(url, handle) {
  if (lockReconnect) return;
  lockReconnect = true;
  //没连接上会一直重连,设置延迟避免请求过多
  setTimeout(function () {
    createWebSocket(url, handle);
    lockReconnect = false;
  }, 2000);
}

//心跳检测
var heartCheck = {
  timeout: 60000,//60秒
  timeoutObj: null,
  serverTimeoutObj: null,
  reset: function () {
    clearTimeout(this.timeoutObj);
    clearTimeout(this.serverTimeoutObj);
    return this;
  },
  start: function () {
    var self = this;
    this.timeoutObj = setTimeout(function () {
      //这里发送一个心跳,后端收到后,返回一个心跳消息,
      //onmessage拿到返回的心跳就说明连接正常
      ws.send("HeartBeat");
      self.serverTimeoutObj = setTimeout(function () {//如果超过一定时间还没重置,说明后端主动断开了
        ws.close();//如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
      }, self.timeout)
    }, this.timeout)
  }
}

/**
 * 打开一个推送
 * @param {String} token                     消息令牌,通过rpc.message.getDefaultToken()可以获取默认令牌
 * @param {Function} handle                  回调,一个参数:msg;id,context,extras成员,extras中有type、ownerId、rawType,rawType不是undefined就是报警
 * @param {String} [url]                     推送服务器,默认v.lanchengiot.net
 */
export default function (token, handle, url = `${socket_url}/data/websocket`) {
  const wsUrl = `${url}/${token.id}/X`;
  createWebSocket(wsUrl, handle);
}

debounce

参考

// 防抖动函数
function debounce(fn,wait=50,immediate) {
    let timer;
    return function() {
        if(immediate) {
            fn.apply(this,arguments)
        }
        if(timer) clearTimeout(timer)
        timer = setTimeout(()=> {
            fn.apply(this,arguments)
        },wait)
    }
}

_.equal

/**
 * 判断此对象是否是Object类型
 * @param {Object} obj  
 */
function  isObject(obj){
    return Object.prototype.toString.call(obj)==='[object Object]';
};
/**
 * 判断此类型是否是Array类型
 * @param {Array} arr 
 */
function isArray(arr){
    return Object.prototype.toString.call(arr)==='[object Array]';
};
/**
 *  深度比较两个对象是否相同
 * @param {Object} oldData 
 * @param {Object} newData 
 */
function equalsObj(oldData,newData){
    //       类型为基本类型时,如果相同,则返回true
     if(oldData===newData)return true;
     if(isObject(oldData)&&isObject(newData)&&Object.keys(oldData).length === Object.keys(newData).length){
         //      类型为对象并且元素个数相同

         //      遍历所有对象中所有属性,判断元素是否相同
         for (const key in oldData) {
             if (oldData.hasOwnProperty(key)) {
                 if(!equalsObj(oldData[key],newData[key]))
                    //      对象中具有不相同属性 返回false
                     return false;
             }
         }
     }else if(isArray(oldData)&&isArray(oldData)&&oldData.length===newData.length){
         //      类型为数组并且数组长度相同

         for (let i = 0,length=oldData.length; i <length; i++) {
            if(!equalsObj(oldData[i],newData[i]))
            //      如果数组元素中具有不相同元素,返回false
            return false;
         }
     }else{
          //      其它类型,均返回false
          return false;
     }
    
     //      走到这里,说明数组或者对象中所有元素都相同,返回true
     return true;
};

json format key

function renameJson(json,oldkey,newkey) {    
 return Object.keys(json).reduce((s,item) => 
      item == oldkey ? ({...s,[newkey]:json[oldkey]}) : ({...s,[item]:json[item]}),{})   
}

单位自管侧边栏菜单(目前两层)

数据结构

const json = [
    {id: '12323', parentId: '66', name: '单位报告' }
    {id: '66', name: '单位档案'}
    ...
]
  • map方案
 const parent = data && Array.isArray(data) && data.filter((item, index) => +item.depth === 3)
  const res = Array.isArray(parent) && parent.map((item) => {
    const children = []
    Array.isArray(data) && data.forEach(v => {
      if (item.id === v.parentId) {
        children.push(v)
      }
    })
    return {
      ...item,
      children
    }
  })
  return res
}

const formatter = (data: Array<any>): Array<any> => {

  const menu = groupBy(data);
  return menu;
}

const memoizeOneFormtter = memoizeOne(formatter, isEqual)

数据中心菜单权限渲染(无限层递归)

let Res, parentKeyMap = {};

function getTree(data) {
  let result = {};
  data.forEach(v => {
    v.parentId = v.parentId || 'ROOT';
    if (!result[v.parentId]) {
      result[v.parentId] = [];
    }
    result[v.parentId].push({
      title: v.name,
      key: v.id.toString(),
      parentId: v.parentId
    });
    parentKeyMap[v.id.toString()] = v.parentId === 'ROOT' ? '' : v.parentId;
  });
  Res = result;
  let tree = [];
  getTreeNode(result['ROOT'], tree);

  return tree;
  // this.setState({ treeData: tree });
}

function getTreeNode(arr, children) {
  arr.forEach(a => {
    if (Res[a.key]) {
      a.children = [];
      children.push(a);
      getTreeNode(Res[a.key], a.children);
    } else {
      children.push(a);
    }
  });
}