一套代码,解决同时适配PC端和移动端的解决方案

2,708 阅读2分钟

一套代码,解决同时适配PC端和移动端解决方案

我之前也查了不少资料找解决方案,大概看了一下,目前主流的就是两种方案

1. 通过两套资源去适配移动端和PC端,判断是PC端还是移动端,去导入不同的路由

2. 通过两套css,一套js逻辑去实现适配移动端和PC端

但是这两套方案都有需要去完成移动端的适配,和PC端的适配(PC端现在主流的电脑屏幕像素差别也很大所以尽量还是也适配吧)

我使用的是 方案2 通过两套css,一套逻辑去完成的,但是不管是方案1 还是 方案2 最终都需要去解决一个适配的问题

适配的方案我也查了很多但是都效果都不太理想,最终的我的方式是:

同时使用 postcss-px-to-viewportpostcss-pxtorem, 使用postcss-pxtorem+ lib-flexible去实现移动端的适配, 使用postcss-px-to-viewport去实现PC端的适配,并且这个插件都是安装到开发环境中,并不会打包进去项目里面,所以直接使用这两种插件对项目而言没有太大的影响

postcss-px-to-viewport 会将 项目中的px在编译时自动转为 vw

postcss-pxtorem+ lib-flexible 会将 项目中的px在编译自动转为 rem

具体实现步骤

  1. 下载 postcss-px-to-viewportpostcss-pxtorem
yarn add postcss-px-to-viewport postcss-pxtorem -D
  1. 下载 lib-flexible
yarn add lib-flexible
  1. 在 mian.js 中引入 lib-flexible
import 'lib-flexible/flexible.js'
  1. 在postcss.config.js 中导入配置,如果没有这个配置文件的话,可以手动在根目录下(于vue.config.js同级)建一个postcss.config.js文件
    1. 这里 postcss-pxtorem 屏蔽了 .pc 和 .el- 的类名,包含 .pc 类名下的子元素,不会被转成 rem
    2. postcss-px-to-viewport屏蔽了 .mobile 类名下的元素的样式,不会被转成 vw
// postcss.config.js

module.exports = {
  plugins: [
    require('postcss-pxtorem')({
      rootValue: 37.5, // 指定跟字号的大小,根据设计稿来,如果设计稿是750px,就制定75
      propList: ['*'], // 需要转换的属性列表,所有属性
      selectorBlackList: ['pc', 'el-'], 
      // 指定一个选择器的黑名单,包含 `"pc"` 或以 `"el-"` 开头的属性不会被转换, 包括 pc下面的 类名
      exclude: [/^node_modules$/, /^styles$/]
      // 表示排除 `node_modules` 目录,`/^styles$/` 表示排除名为 `styles` 的文件夹
    }),
    require('postcss-px-to-viewport')({
      // options
      unitToConvert: 'px', // (String) 需要转换的单位,默认为"px"
      viewportWidth: 1920, // (Number) 设计稿的视口宽度,一般是750
      unitPrecision: 3, //  (Number) 单位转换后保留的精度(很多时候无法整除)
      viewportUnit: 'vw', // (String) 希望使用的视口单位
      selectorBlackList: ['.ignore', '.hairlines', 'mobile', 'el-'],
      /* (Array) 需要忽略的CSS选择器,不会转为视口单位,使用原有的px等单位
      如果传入的值为字符串的话,只要选择器中含有传入值就会被匹配
          例如 selectorBlackList 为 ['body'] 的话, 那么 .body-class 就会被忽略
      如果传入的值为正则表达式的话,那么就会依据CSS选择器是否匹配该正则
          例如 selectorBlackList 为 [/^body$/] , 那么 body 会被忽略,而 .body 不会*/
      minPixelValue: 1, // (Number) 设置最小的转换数值,如果为1的话,只有大于1的值会被转换
      mediaQuery: false, // (Boolean) 媒体查询里的单位是否需要转换单位
      exclude: [/^node_modules$/], // (Array or Regexp) 忽略某些文件夹下的文件或特定文件,例如 'node_modules' 下的文件
      // include:/\/src\/mobile\//
      /* (Array or Regexp) 如果设置了include,那将只有匹配到的文件才会被转换,例如只转换 'src/mobile' 下的文件
      如果值是一个正则表达式,将包含匹配的文件,否则将排除该文件
      如果传入的值是一个数组,那么数组里的值必须为正则
      注意:exclude和include是可以一起设置的,将取两者规则的交集*/
      landscapeUnit: 'vw', // (String) 横屏时使用的单位
      landscapeWidth: 750 // (Number) 横屏时使用的视口宽度
    })
  ]
}
  1. 需要在main.js 中判断当前设备是移动端还是PC端并且挂载到Vue上,用来根据不同设备来为每个页面的根元素添加不同的类名
Vue.prototype.$isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
  1. 需要在每一个组件的根标签去判断当前是移动端还是PC端,应该使用 .pc 还是 .mobile 的类名 ,然后写两套css,对应两个端
<template>
  <div :class="{pc: !$isMobile, mobile: $isMobile}"></div>
</template>

<script>
</script>

<style scoped lang="scss">
.pc {
  /*
    这里写PC端的样式
  */
}

.mobile {
  /*
    这里写移动端的样式
  */
}
</style>