九、响应式发:rem和less(适配移动端)

时间:2021-04-15 18:26:35

一、响应式开发

响应式开发优先适配移动端又兼容到pc端
官网:https://less.bootcss.com/usage/
教程:https://www.w3cschool.cn/less/
rem和em:https://blog.csdn.net/u010132177/article/details/103725945
参考:https://www.jianshu.com/p/58a061c6e9af

1.1安装less依赖

cnpm install less less-loader --save-dev
//记录到devDependencies中,因为这是我们在开发中使用的而非在生产中使用(当然,也可以不加--save-dev)

1.1.2 安装 style-loader、css-loader

cnpm install --save-dev style-loader css-loader

============【待整理】=================================

1.2 添加配置到 build/webpack.base.conf.js

【配置】

,{   //加less配置开始
      test: /.less$/,
      use: [
        "style-loader",
        "css-loader",
        "less-loader"
      ]
    }//加less配置结尾
'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')

function resolve (dir) {
  return path.join(__dirname, '..', dir)
}

module.exports = {
  context: path.resolve(__dirname, '../'),
  entry: {
    app: './src/main.js'
  },
  output: {
    path: config.build.assetsRoot,
    filename: '[name].js',
    publicPath: process.env.NODE_ENV === 'production'
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath
  },
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
    }
  },
  module: {
    rules: [
      {
        test: /.vue$/,
        loader: 'vue-loader',
        options: vueLoaderConfig
      },
      {
        test: /.js$/,
        loader: 'babel-loader',
        include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
      },
      {
        test: /.(png|jpe?g|gif|svg)(?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('img/[name].[hash:7].[ext]')
        }
      },
      {
        test: /.(mp4|webm|ogg|mp3|wav|flac|aac)(?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('media/[name].[hash:7].[ext]')
        }
      },
      {
        test: /.(woff2?|eot|ttf|otf)(?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
        }
      }, {//【配置】加less配置开始
      test: /.less$/,
      use: [
        "style-loader",
        "css-loader",
        "less-loader"
      ]
    }//加less配置结尾]
  },

  node: {
    // prevent webpack from injecting useless setImmediate polyfill because Vue
    // source contains it (although only uses it if it's native).
    setImmediate: false,
    // prevent webpack from injecting mocks to Node native modules
    // that does not make sense for the client
    dgram: 'empty',
    fs: 'empty',
    net: 'empty',
    tls: 'empty',
    child_process: 'empty'
  }
}

1.3 在根目录 index.html下添加代码:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link href="https://cdn.jsdelivr.net/npm/[email protected]" rel="stylesheet" type="text/css">
    <title>hello_vue</title>
  <script>
     (function (doc, win) {
      var docEl = doc.documentElement,
      resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
      recalc = function () {
          var clientWidth = docEl.clientWidth;
          if (!clientWidth) return;
          if(clientWidth>=750){
              docEl.style.fontSize = '100px';
          }else{
              docEl.style.fontSize = 100 * (clientWidth / 750)   'px';
          }
      };

      if (!doc.addEventListener) return;
      win.addEventListener(resizeEvt, recalc, false);
      doc.addEventListener('DOMContentLoaded', recalc, false);
      })(document, window);
  </script>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

代码解释:

<1>设置meta属性  <meta name="viewport" content="width=device-width,initial-scale=1.0">
<script>
<2>运用rem特性进行宽度适配
   (function(){
    let html = document.documentElement,
    hWidth = html.getBoundingClientRect().width;
    console.log(hWidth);
    html.style.fontSize = hWidth/15   "px";//1rem的长度
    })()//根据设计图进行设计,所有的页面完成必须是基于同一个设备或者说是同一分辨率的设备,比如上面代码中的15是可以根据你所选设备的分辨率自行进行选择,最后让font-size为5的倍数,上面代码的核心是保证在不同的设备分辨率下可以动态的调整rem(1rem 就等于 html的font-size)
<3>使用less或者是sass进行css开发,我是基于vue库进行开发的,所以进行如下操作引入less编译器
npm install less less-loader --save//下载less编译器
   {
        test: /.less$/,
        loader: "style-loader!css-loader!less-loader",
      }//在webpack.base.conf.js 中的module模块中加入这都代码
<4> vue中使用less
<style lange="less">
 @rem:25rem //这个值是如何确定的?比如我一开始的屏幕分辨率是基于iphone6 其中宽度为375px,所以此时我设置的font-size :375/15,即此时1rem为25px,所以我此时设置这个变量为25,看下面我对css变量的设置
.main{
     width:280/@rem;//此时如果换在iphone6上面,在设计图上该样式的宽度为280px,这个是固定宽度,不能进行适配,所以我需要将其转尺寸换为rem来表示 此时@rem代表的是你的font-size尺寸(全套页面必须基于同一个设备分辨率来完成)即1rem, 所以280px对应的rem为280/@rem?
}

</style>
<script>
//使用原生js进行设备的适配
(function flexible (window, document) {
  var docEl = document.documentElement
  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();

  // set 1rem = viewWidth / 10
  function setRemUnit () {
    var rem = docEl.clientWidth / 10
    docEl.style.fontSize = rem   'px'
  }

  setRemUnit()

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

  // detect 0.5px supports
  if (dpr >= 2) {
    var fakeBody = document.createElement('body')
    var testElement = document.createElement('div')
    testElement.style.border = '.5px solid transparent'
    fakeBody.appendChild(testElement)
    docEl.appendChild(fakeBody)
    if (testElement.offsetHeight === 1) {
      docEl.classList.add('hairlines')
    }
    docEl.removeChild(fakeBody)
  }
}(window, document))
</script>