Vue 中使用 pxtorem 實現自適應


一、前言

在前端,自適應是不得不考慮的問題。

但是實現自適應有方案也有很多種。今天介紹的是通過在 Webpack 中配置 loader 實現。

還有一個原因,在查資料的時候,網上的一些文章對 postcss-pxtorem、px2rem-loader 用法有些混亂。

特別是 postcss-pxtorem 是 postcss 的 plugin ,px2rem-loader 是一個獨立的 loader 這一點。

所以下面也對這一點做了對比分析。

二、原理、選工具

以前有項目中使用的是 px2rem-loader 這個工具庫。

工作原理是:配置一個 remUnit ,在打包過程中把所有的 px 單位通過換算:

font-size: 16px;

// 轉換 16/remUnit ,remUnit =16
font-size: 1rem;

這樣全局的 px 全部轉換為了 rem。

再配置 html 下的 font-size ,進而設置 rem 的值,達到自適應當前尺寸。

基本原理清除了。繼續搜索了一些這方面的工具庫:

postcss-pxtorem  最近一次更新 9個月前  周下載5w+  

postcss-px2rem   最近一次更新5年前    周下載2k+

px2rem-loader     最近一次更新3年前    周下載2k+

通過對比后打算在項目使用第一個:postcss-pxtorem。

下面對 postcss-pxtorem 和 px2rem-loader 做對比。

三、Postcss-pxtorem

首先下載安裝工具包:

npm install postcss-pxtorem --save-dev

配置:

使用不同的腳手架,其配置方式有所不同。

Vue-cli2

直接在 Webpack 配置項中的 module 中添加 loader配置項:

module: {
    rules: [
        {
            test: /\.(scss|css)$/,
            loaders: [
              'style-loader',
              'css-loader',
              //**************************適配配置開始
              {
                loader: 'postcss-pxtorem', //放在這'style-loader','css-loader'后面,sass-loader前面
                options: {
                  ident: 'postcss', //當引入外部的依賴包作為組件配置項時需要定義一個唯一的標識符,推薦這樣寫
                  plugins: [
                    pxtorem({
                      rootValue: 16, //表示根元素html的fontSize值,也可以是100,獲取任意其他值
                      propList: ['*'], //設置px轉換成rem的屬性值,*表示所有屬性的px轉換為rem
                    }),
                  ],
                },
              },
              //**************************適配部分結束
              'sass-loader',
            ],
        }
    ]
}

因為這個是依賴 postcss 的,所以是放在 postcss-loader 配置項中的 plugins 中。

Vue-cli3

Vue-cli3 中沒有 webpack 單獨的配置問題件,需要在 vue.config.js 中配置。

module.exports = {
// css 配置
  css: {
    loaderOptions: {
      postcss: {
        plugins: [require('tailwindcss'), require('autoprefixer'), require('postcss-pxtorem')({
          rootValue: 16,
          propList: ['*']
        })]
      }
    }
  }
}

postcss 配置文件中設置(.postcssrc.js 或者 postcss.config.js):

注意:這個適用於不同的腳手架,只是這個配置文件的名稱會不一樣

module.exports = {
  plugins: {
    'autoprefixer': {
      browsers: ['Android >= 4.0', 'iOS >= 7']
    },
    'postcss-pxtorem': {
      rootValue: 16,  //結果為:設計稿元素尺寸/16,比如元素寬320px,最終頁面會換算成 20rem
      propList: ['*'],
  selectorBlackList: ['.norem']  // 過濾掉 .norem 開頭的 class,不進行轉換
    }
  }
}

注意:

在最新的項目中使用該插件,報錯:[object Object] is not a PostCSS plugin。

查了一番資料后,原來是版本的問題,由最新的 6.0.0 更新為 5.1.1 (2021年3月25日 更新該問題)。

后續如果使用新的 postcss 的話應該不會出現這個問題。

四、px2rem-loader

因為這個不是依賴於 postcss,所以配置上會不一樣:

這個是直接在 css 文件的 loader 里配置,和其他 loader 同級別

Vue-cli2

module.exports = {
  // ...
  module: {
    rules: [{
      test: /\.css$/,
      use: [{
        loader: 'style-loader'
      }, {
        loader: 'css-loader'
      }, {
        loader: 'px2rem-loader',
        // options 配置
        options: {
          remUni: 75,
          remPrecision: 8
        }
      }]
    }]
  }
}

Vue-cli3

module.exports = {
    chainWebpack: config => {
        config.module
            .rule('scss')
            .test(/\.scss$/)
            .oneOf('vue')
            .use('px2rem-loader')
            .loader('px2rem-loader')
            .before('postcss-loader')
            .options({ remUnit: 75, remPrecision: 8 })
            .end()
    }
}

五、動態修改 rem 對應值

使用上面的 loader,是把代碼中的 px 全部轉換為 rem。要實現自適應,需要動態的改變 html 的 font-size 才可以。

所以要綁定對 window 綁定 onresize 事件。

注意:為了避免其他地方也有需要根據窗口大小變化而變化的,給 onresize 綁定一個回調數組。

/**
 * 根據屏幕變化,自動更改 html 的 font-size
 */

function setRem() {
  const htmlWidth = document.body && document.body.offsetWidth
  const htmlEle = document.getElementsByTagName('html')[0]

  // 默認是在 1920 下 16px,那么對應比例縮放
  htmlEle.style.fontSize = htmlWidth ? (htmlWidth / 1920 * 16 + 'px') : '16px'
}

setRem()

// onresize 回調數組
window.resizeCallbackList = [setRem]
window.onresize = () => {
  window.resizeCallbackList.map(callback => {
    callback()
  })
}

其他地方也需要綁定的時候,直接:

window.resizeCallbackList.push(callback)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM