空对象判断({})
function isEmptyObject(value) {
return value && Object.keys(value).length === 0 && value.constructor === Object;
}
websocket
import { socket_url } from '@/config/query'
var ws;
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) {
reconnect(wsUrl, handle);
};
ws.onerror = function (evnt) {
reconnect(wsUrl, handle);
};
ws.onopen = function (evnt) {
heartCheck.reset().start();
};
ws.onmessage = function (evnt) {
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,
timeoutObj: null,
serverTimeoutObj: null,
reset: function () {
clearTimeout(this.timeoutObj);
clearTimeout(this.serverTimeoutObj);
return this;
},
start: function () {
var self = this;
this.timeoutObj = setTimeout(function () {
ws.send("HeartBeat");
self.serverTimeoutObj = setTimeout(function () {
ws.close();
}, self.timeout)
}, this.timeout)
}
}
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
function isObject(obj){
return Object.prototype.toString.call(obj)==='[object Object]';
};
function isArray(arr){
return Object.prototype.toString.call(arr)==='[object Array]';
};
function equalsObj(oldData,newData){
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]))
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]))
return false;
}
}else{
return false;
}
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: '单位档案'}
...
]
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;
}
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);
}
});
}