屏幕适配方案——详细完备版

打印 上一主题 下一主题

主题 1021|帖子 1021|积分 3063

实用框架:Vue2/Vue3
实用设备:pc端/移动端
适配计谋:动态rem+动态scale
方案效果:可让页面在不同屏幕下、放大缩小时保持页面不变形
  效果示例:
   当屏幕变化时:

    当放大缩小时

  安装屏幕适配插件
  1. npm i screen-adapter-plugin
复制代码
适配写法(推荐):


  • 写class样式时,使用px单位,class内的px单位编译后会转成rem;内联样式需要用px函数px(12)转为rem,px函数已经挂载在Vue的this上。
  • 若想让class样式不被转为rem,可使用.norem-开头的class名称,其大括号范围内所有样式不会被转为rem,或使用大写的PX单位(需要按文档设置postcss.plugin)
  • rem只随视口的宽度动态调节,若想让元素高度随视口高度变化,可使用vh、%或其他单位
  • 内部无法转为rem的插件,例如echarts、relation-graph等,可在元素上绑定v-scale。
    v-scale得当内部没有rem单位的元素,通过transform的scale属性让该元素宽高随视口的宽度自顺应。
    它还可以传入一个监听函数,第一个参数为绑定该指令的元素dom,第二个参数为该元素被放大的倍数,其在视口变化时会自动执行
    1. // 使用方法一,例如echarts元素
    2. <div ref="echartsRef" style="width: 500px;height: 400px;" v-scale></div>
    3. // 使用方法二,传入监听函数
    4. <div ref="echartsRef" style="width: 500px;height: 400px;" v-scale=="handlerAdaptScale"></div>
    5. methods: {
    6.   handlerAdaptScale(el, scale) {
    7.     // do sth...
    8.   },
    9. }
    复制代码
typescript注解:
  1. // px函数注解,可转换为rem,或在第二个入参传入true,获得动态number类型的px
  2. type PX = (px: number, real: boolean) => string | number
  3. // Vue.use时传入的options
  4. interface InstallOptions {
  5.         rootValue: number
  6. }
  7. // 插件提供的方法
  8. interface ScreenAdapter {
  9.         rootFontSize: number // 根元素上动态的font-size
  10.         init(): void         // Vue.use时会自动调用,初始化适配策略
  11.         destroy(): void      // 销毁适配策略
  12.         getScale(): number      // 获得v-scale被放大缩小的倍数
  13.         addListener(callback: Function): void    // 添加屏幕变化时的监听函数
  14.         removeListener(callback: Function): void // 移除屏幕变化时的监听函数
  15.         px: PX
  16. }
复制代码
项目设置
  1. // index.html (防止h5端用户手动放大缩小)
  2. <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0,user-scalable=no;" />
  3. // package.json 安装postcss-plugin-px2rem
  4. "devDependencies": {
  5.   "postcss-plugin-px2rem": "^0.8.1",   
  6. }
  7. // 配置px2rem
  8. // postcss.config.js 写法
  9. module.exports = {
  10.     plugins: {
  11.     'postcss-plugin-px2rem': {
  12.       rootValue: 192, // 设计稿宽度 / 10
  13.       propList: ["*"],
  14.       unitPrecision: 5,
  15.       selectorBlackList: [/.norem-.*/], // 开头为.norem-的class的大括号范围内所有样式不会被转为rem
  16.       ignoreIdentifier: false,
  17.       replace: true,
  18.       mediaQuery: false,
  19.     },
  20.   },
  21. }
  22. // 或者vite.config.js 写法
  23. export default defineConfig({
  24.     css: {
  25.       postcss: {
  26.        plugins: [
  27.         px2rem({
  28.           rootValue: 192, // 设计稿宽度 / 10
  29.           propList: ["*"],
  30.           unitPrecision: 5,
  31.           selectorBlackList: [/.norem-.*/], // 开头为.norem-的class的大括号范围内所有样式不会被转为rem
  32.           ignoreIdentifier: false,
  33.           replace: true,
  34.           mediaQuery: false,
  35.         }),
  36.       ]
  37.     }
  38.   },
  39. })
  40.   
  41.   
  42. // main.js
  43. import screenAdapter from 'screen-adapter-plugin'
  44. Vue.use(screenAdapter, {rootValue: 192}) // 挂载screenAdapter类,传入跟px2rem插件一致的rootValue
  45. // 调用方式
  46. window.screenAdapter
  47. this.screenAdapter
  48. this.px(_,?_)
  49. // 自定义指令使用方式
  50. v-scale
  51. v-scale="handlerAdaptScale"
复制代码
常见问题

  • 放大缩小过程中,有个别元素变形?

    • 写内联样式时,未使用px函数包裹,别的有些组件例如el-table-column的宽度只支持传入px单位的数值,不支持传入rem,可使用px函数px(12, true),将第二个参数设置为true,此时会根据屏幕大小传入动态的px数值
    • 设置父元素line-height:0或者font-size:0
    • 内部无法转化为rem的组件,例如Echarts,可使用v-scale指令

  • 文字边缘模糊?

    • 可以增加css text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; font-smooth: always;或者font-weight: bold;但效果有限

  • Echarts图表样式边缘模糊?

    • 使用svg渲染器 echarts.init(this.$refs.chart, null, { renderer: "svg" })

  • 使用v-scale时会有留白或溢出?

    • v-scale根据视口的宽度缩放元素。假如父元素使用的vh、%这种视口单位,当视口的宽高比小于元素的宽高比,父级元素就会有留白;当父级元素大于元素的宽高比,元素就会有溢出。

      • 这些情况可把v-scale提升到上面父级
      • 内部样式使用不会被转为rem的写法
      适配完让整个页面的底部留白或溢出产生滚动条,这是正常的。
      假如确实不想存在留白或滚动,想要高度也自顺应的页面,可以为元素绑定key值,视口变化时让其重新渲染:
      1. <template>
      2.     <div v-scale :key="scaleKey"></div>
      3. </template>
      4. import { debounce } from "lodash";
      5. export default {
      6.     data() {
      7.       return {
      8.          scaleKey: 1,
      9.       }
      10.     },
      11.     created() {
      12.       // 视口变化时让元素重新绑定v-scale
      13.       this.screenAdapter.addListener(this.debounceRefreshHeightScale);
      14.     },
      15.     beforeDestroy() {
      16.       this.screenAdapter.removeListener(this.debounceRefreshHeightScale);
      17.     },
      18.     methods: {
      19.       debounceRefreshHeightScale: debounce(function () {
      20.         this.scaleKey++;
      21.       }, 500),
      22.     }
      23. }
      复制代码
      此方法比力泯灭性能,请审慎使用!


  • 使用v-scale的元素宽高显示有问题?

    • 假如使用v-scale的元素的宽高使用的百分比,图表就有大概在屏幕变化时由于渲染机遇问题获得错误的宽高,此时可以使用真px值<Echarts width="400px" height="300px"/>让其固定宽高,或用v-if绑定接口的数据来源<Echarts v-if="data.length > 0"/>让其滞后渲染

  • VScode逼迫将大写PX转为小写px

    • 在VScode中使用Vue-official插件,并将其选为默认格式化设置,就不会格式化PX了

  • 为什么设计时不让元素随视口高度缩放?

    • 现在所有视图设计的根本特点就是内容过多时产生垂直滚动条,并且用户天生有向下滚动的直觉,别的浏览器也并未提供可以不停正确有用的拿到视口高度的方法,假如想随视口高度顺应,可自行使用vh、%或其他写法满足需要。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

立聪堂德州十三局店

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表