vue项目 pc端自适配方案

方法一,vue3.0 pc端自适配方案

1.引入插件使用yarn或者npm

yarn add px2rem-loader -S
yarn add postcss-px2rem -S
yarn i lib-flexible -S

npm install px2rem-loader -S
npm install postcss-px2rem -S
npm i lib-flexible -S

2.vue3.0由于没有build配置文件,在根目录新建文件vue.config.js(用来解决跨域或者配置文件)

const autoprefixer = require ('autoprefixer');
// 引入等比适配插件
const px2rem = require('postcss-px2rem')

// 配置基本大小
const postcssRem = px2rem({
  // 基准大小 baseSize,需要和rem.js中相同
  remUnit: 16
})
module.exports = {
  publicPath: "./",
  lintOnSave: true,
  css: {
    loaderOptions: {
      postcss: {
        plugins: [
          postcssRem 
        ]
      }
    }
  }
};

另一种:

module.exports = {
 css: {
   loaderOptions: {
     css: {},
     postcss: {
       plugins: [
         require('postcss-px2rem')({
           remUnit: 192
         })
       ]
     }
   }
 },
}

3.在src下新建util/flexible.js文件

(function(win, lib) {
  var doc = win.document;
  var docEl = doc.documentElement;
  var metaEl = doc.querySelector('meta[name="viewport"]');
  var flexibleEl = doc.querySelector('meta[name="flexible"]');
  var dpr = 0;
  var scale = 0;
  var tid;
  var flexible = lib.flexible || (lib.flexible = {});

  if (metaEl) {
      console.warn('将根据已有的meta标签来设置缩放比例');
      var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/);
      if (match) {
          scale = parseFloat(match[1]);
          dpr = parseInt(1 / scale);
      }
  } else if (flexibleEl) {
      var content = flexibleEl.getAttribute('content');
      if (content) {
          var initialDpr = content.match(/initial\-dpr=([\d\.]+)/);
          var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/);
          if (initialDpr) {
              dpr = parseFloat(initialDpr[1]);
              scale = parseFloat((1 / dpr).toFixed(2));
          }
          if (maximumDpr) {
              dpr = parseFloat(maximumDpr[1]);
              scale = parseFloat((1 / dpr).toFixed(2));
          }
      }
  }

  if (!dpr && !scale) {
      var isAndroid = win.navigator.appVersion.match(/android/gi);
      var isIPhone = win.navigator.appVersion.match(/iphone/gi);
      var devicePixelRatio = win.devicePixelRatio;
      if (isIPhone) {
          // iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
          if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
              dpr = 3;
          } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
              dpr = 2;
          } else {
              dpr = 1;
          }
      } else {
          // 其他设备下,仍旧使用1倍的方案
          dpr = 1;
      }
      scale = 1 / dpr;
  }

  docEl.setAttribute('data-dpr', dpr);
  if (!metaEl) {
      metaEl = doc.createElement('meta');
      metaEl.setAttribute('name', 'viewport');
      metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
      if (docEl.firstElementChild) {
          docEl.firstElementChild.appendChild(metaEl);
      } else {
          var wrap = doc.createElement('div');
          wrap.appendChild(metaEl);
          doc.write(wrap.innerHTML);
      }
  }

  function refreshRem(){
      var width = docEl.getBoundingClientRect().width;
      if (width / dpr > 540) {
          width = width * dpr;
      }
      var rem = width / 100;
      docEl.style.fontSize = rem + 'px';
      flexible.rem = win.rem = rem;
  }

  win.addEventListener('resize', function() {
      clearTimeout(tid);
      tid = setTimeout(refreshRem, 300);
  }, false);
  win.addEventListener('pageshow', function(e) {
      if (e.persisted) {
          clearTimeout(tid);
          tid = setTimeout(refreshRem, 300);
      }
  }, false);

  if (doc.readyState === 'complete') {
      doc.body.style.fontSize = 12 * dpr + 'px';
  } else {
      doc.addEventListener('DOMContentLoaded', function(e) {
          doc.body.style.fontSize = 12 * dpr + 'px';
      }, false);
  }


  refreshRem();

  flexible.dpr = win.dpr = dpr;
  flexible.refreshRem = refreshRem;
  flexible.rem2px = function(d) {
      var val = parseFloat(d) * this.rem;
      if (typeof d === 'string' && d.match(/rem$/)) {
          val += 'px';
      }
      return val;
  }
  flexible.px2rem = function(d) {
      var val = parseFloat(d) / this.rem;
      if (typeof d === 'string' && d.match(/px$/)) {
          val += 'rem';
      }
      return val;
  }

})(window, window['lib'] || (window['lib'] = {}));

4.在main.js里面引入即可

import './util/flexible.js'

方法二,vue2.0 pc端自适配方案

1.安装依赖

npm install px2rem-loader -D            px转rem
npm install lib-flexible -S         阿里可伸缩布局方案

引入:

// main.js
import 'lib-flexible'

2.px转换成rem修改文件:
vue-loader的options和其他样式文件loader最终是都是由build/utils.js里的方法生成的,我们只需在cssLoader后再加上一个px2remLoader即可,px2rem-loader的remUnit选项意思是 1rem=多少像素,结合lib-flexible的方案,我们将px2remLoader的options.remUnit设置成设计稿宽度的1/10,这里假设设计稿宽为1920px:

//  build/utils.js中添加px2remLoader

 const cssLoader = {
    loader: 'css-loader',
    options: {
      sourceMap: options.sourceMap
    }
  }

  // 增加代码,px转rem配置(需要将px2remloader添加进loaders数组中)
  const px2remLoader = {
    loader: 'px2rem-loader',
    options: {
      remUnit: 192,  //根据视觉稿,rem为px的十分之一,1920px  192 rem
      // remPrecision: 8//换算的rem保留几位小数点
    }
  }

//  px2remLoader 放进loaders数组中

function generateLoaders (loader, loaderOptions) {
   const loaders = options.usePostCSS ? [cssLoader, postcssLoader, px2remLoader] : [cssLoader, px2remLoader]

   if (loader) {
     loaders.push({
       loader: loader + '-loader',
       options: Object.assign({}, loaderOptions, {
         sourceMap: options.sourceMap
       })
     })
   }
   //...
 }

3.修改flexible.js
修改flexible.js,在node_modules里面搜,
修改为如下代码:

function refreshRem(){
   var width = docEl.getBoundingClientRect().width;
    if (width / dpr > 540) {
        width = width * dpr;
    }
    //缩放比例,可按实际情况修改
    var rem = width / 8;
    docEl.style.fontSize = rem + 'px';
    flexible.rem = win.rem = rem;
}

4.复制文件,重新引用
接下来把这个文件复制出来,放到lib文件下
然后在main.js中

把import 'lib-flexible'改成import './lib/lib-flexible',

这样就可以在所有项目同步了,不用每个人都改了。

对于不想被转换的样式,可在其后添加/no/保证不被转换:

border-bottom-width: 1px;/*no*/

方法三,其他vue项目,pc端屏幕自适应的方法:

第一步 安装lib-flexible

npm i lib-flexible --save

第二步 在项目入口文件main.js中引入lib-flexible

import 'lib-flexible/flexible.js'

第三步 在项目根目录的index.html 头部删除自动生成的meta标签, lib-flexible会根据屏幕自动生成相对于的meta标签

// 删除
<meta name="viewport" content="width=device-width, initial-scale=1.0">

第四步 使用postcss-pxtorem,用于将像素单元生成rem单位。

//安装依赖
npm install postcss-pxtorem -D

第五步 设置规则(在package.json中配置如下)

"postcss": {
  "plugins": {
   "autoprefixer": {},
    "postcss-pxtorem": {
      "rootValue": 64,
     "propList": [
       "*"
     ]
   }
 }
},

对上面的一些属性解释:

//另一种可以新建postcss.config.js,写入如下代码
module.exports = {
  plugins: {
    // 兼容浏览器,添加前缀
    autoprefixer: {
      overrideBrowserslist: [
        "Android 4.1",
        "iOS 7.1",
        "Chrome > 31",
        "ff > 31",
        "ie >= 8",
        "last 10 versions", // 所有主流浏览器最近10版本用
      ],
      grid: true,
    },
    "postcss-pxtorem": {
      rootValue: 16, //结果为:设计稿元素尺寸/16,比如元素宽320px,最终页面会换算成 20rem
      propList: ["*"], //是一个存储哪些将被转换的属性列表,这里设置为['*']全部,假设需要仅对边框进行设置,可以写['*', '!border*']
      unitPrecision: 5, //保留rem小数点多少位
      //selectorBlackList: ['.radius'],  //则是一个对css选择器进行过滤的数组,比如你设置为['fs'],那例如fs-xl类名,里面有关px的样式将不被转换,这里也支持正则写法。
      replace: true, //这个真不知到干嘛用的。有知道的告诉我一下
      mediaQuery: false, //媒体查询( @media screen 之类的)中不生效
      minPixelValue: 12, //px小于12的不会被转换
    },
  },
};

// 蓝湖上设计稿自定义为375px 测量值直接写入即可 若设计稿为750px 则rootValue: 32

可能的报错处理:PostCSS plugin postcss-pxtorem requires PostCSS 8.

去到package.json文件查看postcss-pxtorem的版本,因为就是它的版本过高了,所以导致这个问题的出现
你只需要把的版本降低到5.1.1就OK了
  • 16
    点赞
  • 112
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值