Skip to content

Vue 移动端适配方案

Published: at 05:30 PMSuggest Changes

正常情况下有 2 个方案,一个是 转 rem 方案一个是转 vw

转 rem 方案 px -> rem

amfe-flexible + postcss-pxtorem

amfe-flexible 原理其实是

项目中引入

// 移动端适配
import 'amfe-flexible/index.js';

postcss.config.js 设置

module.exports = {
  plugins: {
    autoprefixer: {},
    'postcss-pxtorem': {
      rootValue: 37.5, //vant-UI 的官方根字体大小是 37.5
      propList: ['*'],
    },
  },
};

转 viewport 方案 px -> vw

安装 postcss-px-to-viewport

文档:postcss-px-to-viewport

postcss.config.js 设置

module.exports = {
  plugins: {
    autoprefixer: {},
    // Vant 设计稿宽度为 375,其他配置均用默认的
    'postcss-px-to-viewport': {
      // unitToConvert: 'px', // (String) 需要转换的单位,默认为 px
      viewportWidth: 375, // (Number) 视窗的宽度,对应的是我们设计稿的宽度,一般是 750
      // unitPrecision: 5, // (Number) 单位转换后保留的小数位
      // propList: ['*'], // (Array) 指定可以转换的 css 属性,默认是 ['*'],代表全部属性进行转换
      // viewportUnit: 'vw', //  (String) 指定需要转换成的视窗单位,默认 vw
      // fontViewportUnit: 'vw', // (String) 指定字体需要转换成的视窗单位,默认 vw
      // selectorBlackList: [], // (Array) 指定不转换为视窗单位的类,保留 px,值为 string 或正则 regexp
      // minPixelValue: 1, // (Number) 默认值 1,小于或等于 `1px` 不转换为视窗单位
      // mediaQuery: false, // (Boolean) 是否在媒体查询时也转换 px,默认 false
      // replace: true, // (Boolean) 替换包含 vw 的规则
      // exclude: [], // (Array or Regexp) 设置忽略文件,如 node_modules - [/^node_modules$/]
      // landscape: false, // (Boolean) @media (orientation: landscape) 与通过转换的值相加 landscapeWidth
      // landscapeUnit: 'vw', // (String) 横屏时使用的单位
      // landscapeWidth: 568 // (Number) 横屏时使用的视口宽度
    },
  },
};

两者兼容 rem + viewport

使用 转 viewport 方案 之后引入这个 js 脚本就可以了

// 看 https://github.com/amfe/lib-flexible/blob/2.0/index.js 重写的
(function flexible(window, document) {
  const docEl = document.documentElement;
  // https://github.com/evrone/postcss-px-to-viewport/blob/master/index.js
  // 如果你的样式需要做根据视口大小来调整宽度,这个脚本可以将你 CSS 中的 px 单位转化为 vw,1vw 等于 1/100 视口宽度。
  function setRemUnit() {
    const rem = (docEl.clientWidth * 16) / 375; // 16 是 375 设计稿下的字体大小
    docEl.style.fontSize = rem + 'px';
    document.body.style.fontSize = rem + 'px';
  }

  setRemUnit();

  // reset rem unit on page resize
  window.addEventListener('resize', setRemUnit);
  window.addEventListener('pageshow', function (e) {
    if (e.persisted) {
      setRemUnit();
    }
  });
})(window, document);

一处 dpr 的代码引发的思考

var dpr = window.devicePixelRatio || 1;

// adjust body font size
function setBodyFontSize() {
  if (document.body) {
    document.body.style.fontSize = 12 * dpr + 'px';
  } else {
    document.addEventListener('DOMContentLoaded', setBodyFontSize);
  }
}
setBodyFontSize();

iPhoneX 下,字体是 36px,一查 dpr3,然后去 MND 看了一下

MDN - devicePixelRatio

Window 接口的 devicePixelRatio 返回当前显示设备的物理像素分辨率与 CSS 像素分辨率之比。此值也可以解释为像素大小的比率:一个 CSS 像素的大小与一个物理像素的大小。简单来说,它告诉浏览器应使用多少屏幕实际像素来绘制单个 CSS 像素。 当处理标准显示器与 HiDPI 或 Retina 显示器之间的差异时,这很有用,后者使用更多的屏幕像素绘制相同的对象,从而获得更清晰的图像。

devicePixelRatio

后记

参考文章


Previous Post
Vant 样式覆盖问题及解决方法
Next Post
Linux 数据库备份脚本及实践