当前位置: 首页 > 工具软件 > node-rem > 使用案例 >

react 使用postcss-pxtorem 将所有的px转换为rem

刘焱
2023-12-01
最近接了个需求,以前做的pc端的项目要适配,如果适配的话,有两种方案:
媒体查询:麻烦
rem: 更麻烦
**方案:**
所以选择插件 postcss-pxtorem,但是这个插件只能转换css文件中的样式,不能转换行内样式。行内样式要特殊处理,这里的方案就是自定义loader在webpack编译时通过正则拿出px,并通过计算转换。

1.npm install postcss-pxtorem --save
2.配置webapck
在css中配置loader

require('postcss-pxtorem')({ // 把px单位换算成rem单位
              rootValue: 19.20, //换算基数, 
              unitPrecision: 3, //允许REM单位增长到的十进制数字,小数点后保留的位数。
              propList: ['*'],
              exclude: /(node_module)/,  //默认false,可以(reg)利用正则表达式排除某些文件夹的方法,例如/(node_module)/ 。如果想把前端UI框架内的px也转换成rem,请把此属性设为默认值
              // selectorBlackList: ['.ant'], //要忽略并保留为px的选择器,本项目我是用的vant ui框架,所以忽略他
              mediaQuery: false,  //(布尔值)允许在媒体查询中转换px。
              minPixelValue: 1 //设置要替换的最小像素值
            }),

3.rem.js文件

// 基准大小
const baseSize = 16
// 设置 rem 函数
function setRem () {
  // 当前页面宽度相对于 1920 宽的缩放比例,可根据自己需要修改。
  const scale = document.documentElement.clientWidth / 1920
  // 设置页面根节点字体大小, 字体大小最小为12
  let fontSize = (baseSize * Math.min(scale, 2))>12 ? (baseSize * Math.min(scale, 2)): 12;
  document.documentElement.style.fontSize = fontSize + 'px'
}
//初始化
setRem()
//改变窗口大小时重新设置 rem,这里最好加上节流
window.onresize = function () {
  setRem()
}

4.在入口文件引入rem.js
5. 但是行内样式检测不到,所以接下来要做的事就是将行内样式的px转换为rem

暂定解决方案就是在webpack中自定义一个loader:
实现:
1. 创建一个loader文件,在里面创建一个js文件
module.exports = function(content) {
    // let reg = /(\d+(\\.\d+)?)px/g
    let reg = /(?<num1>\d+)\.?(?<num2>\d+)?px/g  // 匹配所有px 相关的字符
    let content1 = content.replace(reg,function(...data){ // px 转换为带小数的rem
          var arr = data[data.length-1]
          var num1=0, num2=0;
          if(arr.num1)num1=parseFloat(arr.num1)
          if(arr.num2)num2=parseFloat(arr.num2)
          return parseFloat(num1+'.'+num2)/207 + 'rem' // 这里以16px 为pc端转换基数 适配1920分辨率
        })
    return content1
  }; 
2.拓展webpack配置,test: /\.(js|mjs)$/,是已经有的,这里的webpack是4.x版本
{
              test: /\.(js|mjs|jsx|ts|tsx)$/,
              include: paths.appSrc,
              use: [
                {
                  loader: require.resolve("babel-loader"),
                  options: {
                    customize: require.resolve("babel-preset-react-app/webpack-overrides"),
    
                    plugins: [
                      [
                        require.resolve("babel-plugin-named-asset-import"),
                        {
                          loaderMap: {
                            svg: {
                              ReactComponent: "@svgr/webpack?-svgo,+titleProp,+ref![path]",
                            },
                          },
                        },
                      ],
                    ],
                    // This is a feature of `babel-loader` for webpack (not Babel itself).
                    // It enables caching results in ./node_modules/.cache/babel-loader/
                    // directory for faster rebuilds.
                    cacheDirectory: true,
                    // See #6846 for context on why cacheCompression is disabled
                    cacheCompression: false,
                    compact: isEnvProduction,
                  },
                }, {
                  loader: path.resolve(__dirname, './loader/style-px2rem-loader.js')
                }
              ],
              // loader: [require.resolve("babel-loader"), path.resolve(__dirname, './loader/style-px2rem-loader.js')],             
              
            },

重点代码块,注意这块代码是在已有的配置中拓展的,是有顺序的:

, {
loader: path.resolve(__dirname, ‘./loader/style-px2rem-loader.js’)
}

  1. 你以为事情到此就结束了嘛,并没有,因为编译时并不能判断屏幕的大小,而且根字体也不能写死,所以还要处理根据自适应屏幕判断根字体的大小变化。
 类似资料: