Ant Design Vue v4版本如何解决1px没有被postcss-px2rem转成rem的问题

背景说明

如果你的 Ant Design Vue 项目有要做适配的需求,那首先要选择一种适配方案。笔者选择的是用 postcss-px2rem 进行适配。笔者在配置了 postcss-px2rem的相关配置后,发现 postcss-px2rem 没有对 Ant Design Vue 进行适配。在网上看了一些文章之后,发现想对 Ant Design Vue 进行适配需要走它自己的规则:给 a-style-provider 组件传入 transformerspropsAnt Design Vue 官方自己提供了一套 transformers 方法,用这套方法可以对大于1px的单位进行转换,而不凑巧的是笔者的项目有对1px进行适配的需求,所以笔者必须解决这个问题。

解决方案

不直接用官方的方案,而是用官方方案的修改版。

编写一个px2rem的方法,然后在 a-style-provider 里引进去。

typescript 复制代码
// 这应该是一个文件,例如px2Rem.ts
import unitless from '@emotion/unitless'
export interface Options {
  /**
   * The root font size.
   * @default 16
   */
  rootValue?: number
  /**
   * The decimal numbers to allow the REM units to grow to.
   * @default 5
   */
  precision?: number
  /**
   * Whether to allow px to be converted in media queries.
   * @default false
   */
  mediaQuery?: boolean
}

const pxRegex = /url\([^)]+\)|var\([^)]+\)|(\d*\.?\d+)px/g

function toFixed(number: number, precision: number) {
  const multiplier = Math.pow(10, precision + 1),
    wholeNumber = Math.floor(number * multiplier)
  return (Math.round(wholeNumber / 10) * 10) / multiplier
}

const transform = (options: Options = {}): Transformer => {
  const { rootValue = 16, precision = 5, mediaQuery = false } = options

  const pxReplace = (m: string, $1: any) => {
    if (!$1) return m
    const pixels = parseFloat($1)
    if (pixels < 1) return m
    const fixedVal = toFixed(pixels / rootValue, precision)
    return `${fixedVal}rem`
  }

  const visit = (cssObj: any): any => {
    const clone: any = { ...cssObj }

    Object.entries(cssObj).forEach(([key, value]) => {
      if (typeof value === 'string' && value.includes('px')) {
        const newValue = value.replace(pxRegex, pxReplace)
        clone[key] = newValue
      }

      // no unit
      if (!unitless[key] && typeof value === 'number' && value !== 0) {
        clone[key] = `${value}px`.replace(pxRegex, pxReplace)
      }

      // Media queries
      const mergedKey = key.trim()
      if (mergedKey.startsWith('@') && mergedKey.includes('px') && mediaQuery) {
        const newKey = key.replace(pxRegex, pxReplace)

        clone[newKey] = clone[key]
        delete clone[key]
      }
    })

    return clone
  }

  return { visit } as Transformer<any, any>
}

export default transform

App.vue该如下

html 复制代码
import px2rem from "./px2Rem.ts" // 自行修改
<template>
  <a-config-provider>
    <a-style-provider :transformers="[px2rem]">
          <component />
    </a-style-provider>
  </a-config-provider>
</template>
相关推荐
weedsfly10 分钟前
异步编程全景与事件循环——彻底搞懂 JS 执行机制
前端·javascript
用户0595401744610 分钟前
AI Agent记忆测试踩坑实录:Mock骗了我一周,Mem0+pytest一招破局
前端·css
用户17335980753711 分钟前
纯前端 PDF 数字签名实战:Vue 3 + pdf-lib 在浏览器里完成签名嵌入
前端·javascript
IT_陈寒1 小时前
SpringBoot自动配置的坑,我爬了三天才出来
前端·人工智能·后端
Avan_菜菜8 小时前
AI 能写代码了,为什么我反而开始要求它先写文档?
前端·github·ai编程
爱勇宝12 小时前
鸿蒙生态的下半场:开发者不只要能开发,还要能赚钱
android·前端·程序员
IT_陈寒15 小时前
SpringBoot这个自动配置坑我跳了三次
前端·人工智能·后端
kyriewen15 小时前
我用 AI 一周写完了整个项目,上线第一天就崩了——这是我踩过最贵的 5 个坑
前端·javascript·ai编程
牧艺16 小时前
从零到协同:构建类飞书在线文档系统的五个技术重难点
前端·人工智能
红尘散仙16 小时前
想写一个像样的终端 App?试试把 React 的开发体验搬进 Rust TUI
前端·rust