1. LocalStorage 操作方法
1.1 获取
export function getStorage(key) {
const data = localStorage.getItem(key);
if (!data) {
return null;
}
try {
const json = JSON.parse(data);
return json;
} catch(e) {}
return data;
}
1.2 设置/更新
export function setStorage(key, data) {
if (typeof data === "string") {
localStorage.setItem(key, data);
return;
}
let old = getStorage(key);
if (!old) {
localStorage.setItem(key, JSON.stringify(data));
return;
}
try {
old = JSON.parse(old);
let json = Object.assign({}, old, data);
localStorage.setItem(key, JSON.stringify(json));
} catch(e) {
localStorage.setItem(key, JSON.stringify(data));
}
}
1.3 删除
export function delStorage(key) {
if (key) {
localStorage.removeItem(key);
} else {
localStorage.clear();
}
}
2. 策略模式
策略模式(Strategy Pattern)是一种行为设计模式,它让你可以定义一系列算法,并将每个算法封装起来,使它们可以相互替换。通过这种方式,程序运行时可以根据需要在各个算法之间进行动态切换,从而达到灵活、可扩展的效果,示例代码:
class TaxCalculator {
constructor(strategy) {
this.strategy = strategy;
}
calculate(price) {
return this.strategy.calculateTax(price);
}
}
class BasicTaxStrategy {
calculateTax(price) {
return price * 0.1;
}
}
class ProTaxStrategy {
calculateTax(price) {
return price * 0.2;
}
}
const calculator = new TaxCalculator(new BasicTaxStrategy());
console.log(calculator.calculate(100)); // 输出10
calculator.strategy = new ProTaxStrategy();
console.log(calculator.calculate(100)); // 输出20
在上述代码中,我们首先定义了一个名为TaxCalculator的类,该类包含一个构造函数和一个calculate()方法。在构造函数中,我们接收了一个strategy参数,并将其存储在实例对象的strategy属性中。在calculate()方法中,我们调用了strategy对象的calculateTax()方法,以计算出价格所应缴纳的税费。
接下来,我们又定义了两个名为BasicTaxStrategy和ProTaxStrategy的类,这两个类分别代表了不同的计算取税策略。在这两个类中,我们都定义了一个calculateTax()方法,并在其中实现了不同的税费计算方法。
最后,我们创建了一个名为calculator的TaxCalculator实例,并将其初始化为BasicTaxStrategy策略对象。接着,我们调用了calculate()方法来计算传入的价格所应缴纳的税费。当我们需要切换计算税费的策略时,我们只需要将strategy属性设置为其他的策略对象即可,如上述代码中第二次调用calculate()方法时所示。
通过上述代码示例,我们可以看到,使用策略模式可以使程序具有更好的可扩展性和灵活性。如果需要增加、修改或删除一种计算税费的策略,只需添加、修改或删除相应的策略类即可,而无需对程序中的其他部分进行任何修改。
其他应用:前端设计模式之策略模式 - 掘金 (juejin.cn)
3.关键词命中高亮
基本流程(按自己的业务取修改):
- 处理不同关键字形成新的关键字数组
- 获取所有关键词命中区间
- 合并关键字区间
- 关键词高亮
- 各步骤日志
//获取关键字区间数组:[[start1, end1], [start2, end2], ...]
function getInterval(word, content, isIgnore = false) {
const REG = new RegExp(word,`${isIgnore ? 'gi': 'g'}`)
let interval = []
let target = null
while((target = REG.exec(content)) !== null) {
let s = target.index
interval.push([s, s + word.length - 1])
}
return interval
}
/**
* @description 1.将数组按照第一位的大小进行排序(sort方法)
* 2.创建 新的数组 和 临时空间
* 3.从 临时空间 和 当前数组cur 进行判断
* 如果有重合的,将其合并,放入 临时空间 中。
* 如果没有重合的,将 临时空间 中的数组放入 新建的数组 中。
* 4.循环第3步
* @param {number[][]} interval
* @return {number[][]}
*/
function mergeInterval(interval) {
if(interval.length === 0) return []
interval.sort((a, b) => a[0] - b[0]) //1
let res = []//2.
let candidate = interval[0] //2.临时空间
for (let i = 1; i < interval.length; i++) {
let cur = interval[i] //3.第二个区间开始对比区间
if (candidate[1] >= cur[0]) {
//有重合, 合并(左侧为临时空间的左侧:不变, 右侧取两区间之间的最大值)
candidate[1] = Math.max(candidate[1], cur[1])
} else {
//无重合,不合并,修改临时空间的值(用于下一区间比较)
res.push(candidate)
candidate = cur
}
}
//把最后一项也添加到结果中
if(candidate.length !== 0) {
res.push(candidate)
}
return res
}
function highLight(content, keywordInterval, isBold) {
//关键字逆序 -> 从内容后方开始按范围添加span高亮标签不会受数组长度变化的影响
const intervals = keywordInterval.sort((a, b) => b[0] - a[0])
const contentArr = content?.split('')
intervals.forEach(interval => {
const [s , e] = interval
contentArr.splice(s, 0, `<span style="color:red ${isBold ? ';font-weight: bold' : ''} ">`)
contentArr.splice(e + 2, 0, '</span>')
})
return contentArr.join('')
}
/**
* @param {string} content -文本内容
* @param {string[]} keywordArr -关键字数组,支持类型:你好、你|好、你|好~~~3
* @param {boolean} isIgnore -是否忽略大小写(默认false)
* @param {boolean} showLog -是否打印日志(默认false)
* @param {boolean} isBold -文本是否加粗(默认false)
* @returns {JSX} 添加span标签的高亮文本
*/
function highLightKeyword(content = '', keywordArr = [], isIgnore = false, showLog = false, isBold = false) {
//如果内容为空直接return
if (!content.length) return
const filterWord = []
let keywordMergeInterval = []
let keywordInterval = []
let highLightContent = ''
//一、处理不同关键字形成新的关键字数组
keywordArr.forEach(word => {
switch (true) {
case word.length !== 0 && word.indexOf('|') === -1: filterWord.push(word)
break
//处理间隔关键词:如:'你|好~~~3'--> '你|好' --> ['你','好']
case word.indexOf('|') !== -1: filterWord.push(...word.replace(/~+\d/ig, '').split('|'))
break
default: return
}
})
//二、获取所有关键词命中区间
filterWord.forEach(word => getInterval(word, content, isIgnore).length !== 0 && keywordInterval.push(...getInterval(word, content, isIgnore)))
//三、合并关键字区间
keywordMergeInterval = mergeInterval(keywordInterval)
//四、关键词高亮
highLightContent = highLight(content, keywordMergeInterval, isBold)
//五、各步骤日志
if (showLog) {
console.log('关键字数组---', filterWord)
console.log('关键字出现区间---', keywordInterval)
console.log('合并后关键字出现区间---', keywordMergeInterval)
console.log('文本高亮---', highLightContent)
}
return highLightContent
}
export default highLightKeyword
4.获取静态资源
- 该函数的主要用途是生成一个完整的资源路径,方便在应用程序中引用静态文件,例如图片、样式表等。通过使用
BASE_URL,可以确保在不同的环境(如开发、测试和生产)中都能正确解析资源路径,避免硬编码 URL。 return import.meta.env.BASE_URL + path;:import.meta是一个特殊的对象,在 ES模块内可用,用于访问一些元信息。import.meta.env通常用于环境变量,尤其是在像 Vite 等现代构建工具中。BASE_URL是一个环境变量,代表基础 URL,通常用于指向静态资源或公共目录的地址。- 该行代码将
BASE_URL与传入的path进行拼接,并返回这个完整的路径。
/**
* 获取静态资源路径
* @param path
* @example publicDirResource("/image/logo.png")
* @returns
*/
export function publicDirResource(path: string) {
return import.meta.env.BASE_URL + path;
}