Skip to content

笔记

✏️ XFeng    丨    🕙 2025-12-30    丨    笔记📒

✍️好记性不如烂笔头


JS/TS相关

数组对象去重

根据某个字段去重

1.遇到重复保留最后一次出现的数据

js
const dedupeByKey = <T extends Record<string, any>, K extends keyof T>(array: T[], key: K): T[] => {
    const map = new Map<T[K], T>()
    array.foreach(item => map.set(item[key], item))
    return [...map.values()]
}

2.遇到重复保留第一次出现的数据

js
const  dedupeByKey = <T extends Record<string, any>, K extends keyof T>(array: T[], key: K): T[] => {
    const set = new Set<T[K]>()
    return arrary.filter(item => {
        if (set.has(item[key])) return false
        set.add(item[key])
        return true
    })
}

取默认值

下面是两种常见的取默认值写法:

js
/** example1 */
const result = object.value || "default"

/** example2 */
const result = object.value ?? "default"

区别

  • || 是逻辑或运算符,当左侧表达式是假值(false value)的时候,返回右侧的结果,否则返回左侧的结果
  • ?? 是空值合并运算符,当左侧表达式为 nullundefined 时,返回右侧的结果,否则返回左侧的结果

假值(false value)

  • false
  • 0
  • "" (空字符串)
  • null
  • undefined
  • NaN

总体来说 || 范围更广包含了 ?? 在内,?? 只有在 nullundefined 时才会触发。


下载图片,触发浏览器保存

适用场景:后端返回文件地址,想实现点击下载,触发浏览器保存

方法一(代码简单,但如果服务器设置图片不能下载,则无法触发浏览器保存):

js
const downloadFile = (url: string) => {
  const link = document.createElement("a")
  link.href = url
  link.download = "文件名"
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}

方法二(比较万能,但是会有跨域问题,原理是使用canvas):

js
const downloadFile = (url: string, name: string) => {
  let image = new Image()
  image.setAttribute("crossOrigin", "anonymous")
  image.src = url
  image.onload = () => {
    let canvas = document.createElement("canvas")
    canvas.width = image.width
    canvas.height = image.height
    let ctx = canvas.getContext("2d")
    if (ctx) {
      ctx.drawImage(image, 0, 0, image.width, image.height)
      canvas.toBlob((blob) => {
        if (blob) {
          let url = URL.createObjectURL(blob)
          let eleLink = document.createElement("a")
      eleLink.download = name
          eleLink.href = href
          eleLink.click()
          eleLink.remove()
          // 用完释放URL对象
          URL.revokeObjectURL(url)
        }
      })
    }
  }
}

下载文件,触发浏览器保存(终极方案)

适用场景:后端返回文件地址,想实现点击下载,触发浏览器保存。无论是图片、文件都可以,可以接受流也可以接受文件URL

js
/**
 * 通用文件下载方法,支持图片、Excel、PDF等文件类型
 * @param {string|Blob} source - 文件URL或Blob对象
 * @param {string} filename - 下载的文件名(带扩展名)
 */
export const downloadFile = async (source: string | Blob, filename: string) => {
  if (!source) return

  try {
    // 处理Blob对象
    if (source instanceof Blob) {
      const url = URL.createObjectURL(source)
      const link = document.createElement("a")
      link.href = url
      link.download = filename
      document.body.appendChild(link)
      link.click()

      // 清理资源
      setTimeout(() => {
        document.body.removeChild(link)
        URL.revokeObjectURL(url)
      }, 100)
      return
    }

    // 处理URL
    // 对于跨域文件,使用 fetch 获取文件内容
    const response = await fetch(source)
    const blob = await response.blob()

    // 创建临时 URL
    const blobUrl = window.URL.createObjectURL(blob)

    const link = document.createElement("a")
    link.href = blobUrl
    link.download = filename // 添加扩展名
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)

    // 清理临时 URL
    window.URL.revokeObjectURL(blobUrl)
  } catch (error) {
    // 如果 fetch 失败,回退到直接打开
    window.open(source as string)
  }
}

Vue相关

文件流转图片显示

适用场景:后端返回图片流,前端直接显示(可以用img标签)。适用于二维码显示、预览图片显示等

js
const captchaImage = ref("")
const getImage = async () => {
 // 请求接口获取图片流
 const res = await getCodeImageApi()
 // 获取图片
 const blob = new Blob([res.data], { type: "image/jpeg" })
   captchaImage.value = URL.createObjectURL(blob)
}

CSS相关

通用两栏文字排版做法【grid终极方案】

html
<style>
.box {
  display: grid;
  grid-template-columns: max-content 1fr; // 两列,第一列宽度自适应内容,第二列占满剩余空间
  row-gap: 16px;
  column-gap: 24px;
  align-items: center;
}
</style>

<div class="box">
  <div>手机号</div>
  <div>13888888888</div>

  <div>地址</div>
  <div>广东省深圳市某某区某某街道</div>

  <div>商品支付超时等待订单</div>
  <div>这是一条很长的label</div>

  <div>L</div>
  <div>这是一条很短的label</div>
</div>

图片闪烁/呼吸灯效果

css
img {
  animation: blink 3s infinite; /* 设置图片动画 */
}
 
@keyframes blink {
  0% {
    opacity: 1; /* 动画开始时不透明 */
  }
  50% {
    opacity: 0; /* 动画中间时完全透明 */
  }
  100% {
    opacity: 1; /* 动画结束时重新不透明 */
  }
}

color-mix() 函数

代码举例:

css
background: color-mix(in srgb, var(--el-menu-active-color) 10%, transparent)

参数说明:

  • in srgb: 指定颜色空间为 sRGB(标准红绿蓝色彩空间)
  • var(--el-menu-active-color) 10%: 使用 CSS 自定义属性(CSS 变量)作为第一个颜色,占混合比例的 10%
  • transparent: 第二个颜色是透明色,占剩余的 90%

效果: 这会创建一个半透明版本的背景颜色,透明度为 90%

其他用法举例:

css
// 混合红色和蓝色,各占50%
background: color-mix(in srgb, red, blue);

// 红色占70%,蓝色占30%
background: color-mix(in srgb, red 70%, blue);

// 将主题色与白色混合,创建较浅的版本
background: color-mix(in srgb, var(--primary-color) 20%, white);

// 创建悬停效果
.button {
  background: var(--button-color);
  
  &:hover {
    background: color-mix(in srgb, var(--button-color) 80%, white);
  }
}

不同颜色空间

css
// 使用不同的颜色空间进行混合
color-mix(in hsl, red, blue) // HSL 色彩空间
color-mix(in hwb, red, blue) // HWB 色彩空间  
color-mix(in lab, red, blue) // LAB 色彩空间

总结:

color-mix能做到与rgba一样的效果,但两者之间有细微区别:rgba更加通用简单,但是不适合带有变量的参数,而color-mix能做到使用变量来实现透明度。

TIP

⚠️ color-mix() 是相对较新的 CSS 功能,需要检查目标浏览器支持情况


electron

加密打包后的程序源码

1.安装**asar**

bash
# pnpm下载
pnpm i asar -g

# npm下载
npm install asar -g

2.在resources目录下使用asar指令进行加密

bash
asar pack ./app app.asar

加密后结果如下:

image-20250624103635983

3.删除app文件后重新打开程序,没问题代表加密成功

Released under the MIT License.