【Vue移动端】实现 字体大小 自适应

7,895 阅读3分钟

一、背景

  • 最近一直有用户反馈页面的在 iPad 上显示的内容非常小,页面上的文字看不清楚
  • 大的屏幕 理应看到更大的图标和文字,结果却没有达到预期

二、问题

  • 页面大小没有根据 移动设备的视口宽度 进行自适应
  • 由于项目成立的时间比较长,工程中 css 的 单位不统一,例如:px / em / rem 等

三、对问题的思考

  • 如何 实现 页面 根据 视口的宽度进行自适应?
  • 如何对这么多的 px 单位进行转换?

四、复习 em / rem

  • em

    em

  • rem 英文的完整翻译是:Root Element

    rem

截图来自: MDN
链接:https://developer.mozilla.org/zh-CN/docs/Web/CSS/length

五、解决问题的思考

1. 在网上查找了大量的资料,业界的主要解决方案是 rem,因此楼主也采用了 rem 的方式。
   采用 rem 的方式,那自然是引入了 amfe-flexible 库进行实现。问题1迎刃而解

2. 如何实现工程中的 px 转 rem,这是一个头疼的问题。
    2.1 直接手动把工程中的所有 px 换算为 rem ? 这不现实,成本太高
    2.2 写一个工具先把 工程中的所有 px 换算为 rem ? 这可行,但是还是不够自动化,后期维护恶心
    2.3 webpack 打包的时候,把 px 转 rem ? 这可行,实现之后,后期无需维护,只要随着工程构建,就可以实现转换

六、代码的实现

解决问题 1
  • 引入 amfe-flexible 实现根节点 rem 配置
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
    <!--这里的文件可以根据自己的实际情况,将源码copy一份进行修改-->
    <script src="./node_modules/amfe-flexible/index.js"></script>
</head>
解决问题 2
  • 首先我们知道,loaders 装载器的运行顺序是 从后往前;pulgins 外挂的 执行顺序是 从前往后。
  • 那么即使我们在工程中使用 less / sass 写样式,最后还是要经过 css-loader 进行处理,那么我们 对 px 转 rem 的操作,只需要在 less-loader/sass-loader 和 css-loader 之间进行即可
  • 楼主采用的 px2rem-loader
  • 由于项目工程 是 vue-cli2 搭起来的,因此我们找到 util.js
1. 安装

yarn add px2rem-loader -D

2. util.js 配置

exports.cssLoaders = function (options) {
    options = options || {}

    const cssLoader = {
        loader: 'css-loader',
        options: {
            minimize: process.env.NODE_ENV === 'production',
            sourceMap: options.sourceMap,
            importLoaders: 1
        }
    }

    // 关键点 !!
    const px2remLoader = {
        loader: 'px2rem-loader',
        options: {
            remUnit: 50, // 项目规范以50px为基准数,可根据自己额实际情况而定
            exclude: /(node_module)/
        }
    }

    // generate loader string to be used with extract text plugin
    function generateLoaders (loader, loaderOptions) {
        let loaders = [cssLoader, px2remLoader]
        if (loader) {
            loaders.push({
                loader: loader + '-loader',
                options: Object.assign({}, loaderOptions, {
                    sourceMap: options.sourceMap
                })
            })
        }

        // Extract CSS when that option is specified
        // (which is the case during production build)
        if (options.extract) {
            return ExtractTextPlugin.extract({
                use: loaders,
                fallback: 'vue-style-loader'
            })
        } else {
            return ['vue-style-loader'].concat(loaders)
        }
    }

    // http://vuejs.github.io/vue-loader/en/configurations/extract-css.html
    return {
        css: generateLoaders(),
        postcss: generateLoaders(),
        less: generateLoaders('less'),
        sass: generateLoaders('sass', { indentedSyntax: true }),
        scss: generateLoaders('sass'),
        stylus: generateLoaders('stylus'),
        styl: generateLoaders('stylus')
    }
}

若有些特定的情形不需要转换 px,那可进行如下配置

.selector {
  width: 150px;
  height: 64px; /*px*/
  font-size: 28px; /*px*/
  border: 1px solid #ddd; /*no*/
}
px2rem-loader 基于 px2rem 实现,很多用法和 px2rem 类似

https://github.com/Jinjiang/px2rem-loader

配置完成,本地运行,看到如下效果,我们就完成了一大步

七、遇到的问题

  • 打包构建时出现以下的错误

  • 解决方案: 升级 happypack,问题解决

// package.json

"devDependencies": {
    "happypack": "5.0.1",
    "px2rem-loader": "^0.1.9"
}

最后祝大家一起进步!好好学习不会差