背景说明
如果你的 Ant Design Vue
项目有要做适配的需求,那首先要选择一种适配方案。笔者选择的是用 postcss-px2rem
进行适配。笔者在配置了 postcss-px2rem
的相关配置后,发现 postcss-px2rem
没有对 Ant Design Vue
进行适配。在网上看了一些文章之后,发现想对 Ant Design Vue
进行适配需要走它自己的规则:给 a-style-provider
组件传入 transformers
的 props
。Ant 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>