vue3-h5项目适配各种手机

1,484 阅读3分钟

主要通过amfe-flexiblepostcss-pxtorem

amfe-flexible

  1. 作用:用于动态设置 HTML 根元素的 font-size,从而实现基于 rem 的响应式布局。

  2. 使用:

    • 安装:npm install amfe-flexible
    • 引入:在 main.jsimport 'amfe-flexible'
  3. 可以在控制台验证下是否根据不同机型设置了font-size

    image.png

postcss-pxtorem

  1. 作用:将px自动转化为rem,解放双手。

  2. 使用

    • 安装:npm install postcss-pxtorem

    • 配置:根目录下创建postcss.config.js文件

      // postcss.config.js
      module.exports = {
        plugins: {
          'postcss-pxtorem': {
            rootValue: 37.5,
            propList: ['*'],
            selectorBlackList: ['html'],
            minPixelValue: 2,
            exclude: (e) => { // 只对src/views/pages文件进行px转rem,其他文件不转换
              if(/src(\\|\/)pages/.test(e)) {
                return false
              } else {
                return true
              }
            }
          },
          'autoprefixer': {}
        }
      };
      
      
  3. 配置项说明

    1. rootValue:指定 px 转换为 rem 的基准值。一般若设计稿宽度是375px则设置为37.5。(也可以传入一个函数,根据文件路径动态返回不同的值)
    2. unitPrecision:指定 px 转换为 rem 时的小数位数,通常不需要修改。
    3. propList:指定哪些属性需要进行转换,可以使用通配符 *,也可以具体指定某些属性。比如:propList: ['*', '!border*']
    4. selectorBlackList:指定不需要进行转换的选择器,支持正则表达式。
    5. replace:是否直接替换属性值,而不是添加备用属性。
    6. mediaQuery:是否允许在媒体查询中进行转换。
    7. minPixelValue:设置需要转换的最小像素值,所有小于等于该值的 px 单位将不会被转换。
    8. exclude:指定不需要进行转换的文件,支持字符串、正则表达式或函数。

按需适配

事情并不总是完美的,比如接手了一个项目,前期并没有使用如上方案,是用了vw或者直接用的px。但是原来的页面看起来还算正常。

总之为了不影响原来的页面,同时又在以后的开发中引入如上方案,可以考虑这样。

  1. amfe-flexible只在meta开启useAmfeFlexible页面引入
  2. pxtorem只对pages文件夹下的内容进行更改,原来部分不改动。(pages文件夹可以根据你自己的项目定义,当然该文件夹下的所有页面都要开启useAmfeFlexible)

配置postcss-pxtorem转化部分文件

// postcss.config.js
module.exports = {
  plugins: {
    'postcss-pxtorem': {
      rootValue: 37.5,
      propList: ['*'],
      selectorBlackList: ['html'],
      minPixelValue: 0,
      exclude: (e) => { // 只对src/pages文件进行px转rem,其他文件不转换
        if(/src(\\|\/)pages/.test(e)) {
          return false
        } else {
          return true
        }
      }
    },
    'autoprefixer': {}
  }
};

按需引入 amfe-flexible

准备工具函数:

// utils/amfeFlexible.js
export function loadFlexible() {
    const script = document.createElement('script');
    script.src = 'https://cdn.jsdelivr.net/npm/amfe-flexible/index.min.js';
    script.id = 'amfe-flexible-script';
    document.head.appendChild(script);
}

export function unloadFlexible() {
    const script = document.getElementById('amfe-flexible-script');
    if (script) {
        document.head.removeChild(script);
    }
    const htmlElement = document.documentElement;
    htmlElement.removeAttribute('style');//移除html元素上amfe-flexible添加的style属性
}

通过路由导航判断是否引入amfe-flexible

import {loadFlexible,unloadFlexible} from '../utils/amfeFlexible';
router.beforeEach((to, from, next) => { 
    // 根据meta的配置确定是否启用amfe-flexible
    if(to.meta.useAmfeFlexible){
        loadFlexible();
    }else{
        unloadFlexible();
    };
    next();
})

问题

当然这也不是完美的,当访问开启useAmfeFlexible页面后,再访问没有开启useAmfeFlexible的页面,没有开启useAmfeFlexible的页面字体大小可能会受到影响

强制刷新或者设置没有开启useAmfeFlexible的页面的font-size为默认值即可,只能发生这种情况的时候单独处理了。

不会被转化

  1. propList中配置的以"!"开头的内容
  2. selectorBlackList配置的选择器
  3. 行内样式