小小小工具函数

133 阅读4分钟

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;
}