kpmg-smart-table
Version:
148 lines (130 loc) • 3.59 kB
JavaScript
/**
* 防抖函数
* @param {Function} fn 需要防抖的函数
* @param {Number} delay 延迟时间(ms)
* @returns {Function} 防抖处理后的函数
*/
export function debounce(fn, delay = 300) {
let timer = null;
return function(...args) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
timer = null;
}, delay);
};
}
/**
* 节流函数
* @param {Function} fn 需要节流的函数
* @param {Number} wait 等待时间(ms)
* @returns {Function} 节流处理后的函数
*/
export function throttle(fn, wait = 300) {
let previous = 0;
let timer = null;
return function(...args) {
const now = Date.now();
const remaining = wait - (now - previous);
if (remaining <= 0 || remaining > wait) {
if (timer) {
clearTimeout(timer);
timer = null;
}
previous = now;
fn.apply(this, args);
} else if (!timer) {
timer = setTimeout(() => {
previous = Date.now();
timer = null;
fn.apply(this, args);
}, remaining);
}
};
}
/**
* 函数缓存
* @param {Function} fn 需要缓存的函数
* @returns {Function} 缓存处理后的函数
*/
export function memoize(fn) {
const cache = new Map();
return function(...args) {
const key = JSON.stringify(args);
if (cache.has(key)) {
return cache.get(key);
}
const result = fn.apply(this, args);
cache.set(key, result);
return result;
};
}
/**
* RAF节流
* 使用requestAnimationFrame实现的节流函数
* @param {Function} fn 需要节流的函数
* @returns {Function} 节流处理后的函数
*/
export function rafThrottle(fn) {
let locked = false;
return function(...args) {
if (locked) return;
locked = true;
window.requestAnimationFrame(() => {
fn.apply(this, args);
locked = false;
});
};
}
/**
* 计算字符串显示宽度(粗略)
* 用于表格自动宽度计算
* @param {String} str 要计算的字符串
* @returns {Number} 字符宽度(px)
*/
export function calcTextWidth(str) {
if (!str) return 0;
// 英文字符和数字宽度为10px, 中文字符宽度为18px
let width = 0;
for (let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i);
// 中文字符范围
if (char >= 0x4e00 && char <= 0x9fa5) {
width += 18;
} else {
width += 10;
}
}
return width;
}
/**
* 自动计算表格列宽
* @param {String} fieldName 字段名
* @param {Array} data 表格数据
* @param {String} title 列标题
* @param {Number} min 最小宽度
* @param {Number} max 最大宽度
* @returns {Number} 建议列宽
*/
export function flexColumnWidth(fieldName, data = [], title = '', min = 80, max = 250) {
// 标题宽度
const titleWidth = calcTextWidth(title) + 30; // 30px为内边距
if (!fieldName || !data || !data.length) {
return Math.max(min, titleWidth);
}
// 内容最大宽度
let maxContentWidth = 0;
for (let i = 0; i < data.length; i++) {
const item = data[i];
const value = item[fieldName];
if (value !== undefined && value !== null) {
const valueStr = value.toString();
const currentWidth = calcTextWidth(valueStr) + 30; // 30px为内边距
maxContentWidth = Math.max(maxContentWidth, currentWidth);
}
}
// 取标题宽度和内容宽度的最大值
const suggestedWidth = Math.max(titleWidth, maxContentWidth);
// 限制在最小和最大宽度之间
return Math.min(max, Math.max(min, suggestedWidth));
}