博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Weex布局尺寸通用适配方案的研究
阅读量:6971 次
发布时间:2019-06-27

本文共 2703 字,大约阅读时间需要 9 分钟。

问题

weex为前端赋予了强大的跨端开发能力和较一致的良好的用户体验。weex一般是与native进行协作开发:

  1. 同app内不同页面用两者分别开发,统一串联
  2. 同页面两者协作开发,比如native提供组件,weex使用

由于native布局一般采用定高不定宽的方式,以求不同尺寸的屏幕可以得到基本一致的布局体验,然而weex布局采用基于750的等比例缩放,这种不一致导致的问题:

  1. 同一元素在不同屏幕的尺寸展现不一致,大屏手机尺寸偏大,小屏手机尺寸偏小
  2. 与native尺寸偏差较多

字号的差异也比较明显。

默认依据ip6尺寸布局,惨不忍睹的现场直击...

  • 红框部分的滑动组件是native的,而背景容器是weex布局的,由于weex等比例缩放,而native使用pt,导致iphone 5s native组件溢出,而iphone 6p组件相比于容器过小。

数据流图

  • 下面是iphone 6p下native列表和weex列表字号对比

思考及分析

weex目前的尺寸处理方式:

无视屏幕分辨率和尺寸,虚拟宽度统一为750,布局尺寸以750为基准按比例缩放。

那么使用weex原生尺寸定义想实现native的体验“在不同尺寸手机上同样元素的尺寸基本一致”是不太可能的。

不过weex在Js运行时提供了屏幕的物理分辨率和像素比例,那么运行时可不可以用js动态算一下呢?

我们定义weex的原生尺寸为vp(virtual pixel),视觉稿的尺寸或native的尺寸为ns(native size)。

期待的转换规则为

vp = translateRule(dp)

这样用户只需要按native的方式写布局尺寸,就可以映射为weex的尺寸,被weex布局逻辑动态解析,从而达到我们的目的。

既然我们要模拟Native的尺寸适配,首先要知己知彼,简单了解了一下native的适配方法

安卓尺寸适配

安卓提供了一个万能的适配单位:dp,dp屏蔽了屏幕大小和分辨率,提供了一致体验,dp和物理像素的换算关系如下:

dp = px / (dpi / 160)

欲转换先取dpi,可惜weex没有dpi,但提供了一个比例scale,可用来计算dpi

scale = dpi / 160

换算可得

vp = dp * 750 / ( deviceWidth / scale )

IOS尺寸适配

类似dp的单位是着色器(似乎等同于pt?)

pt = px / scale

换算可得

vp = pt * 750 / ( deviceWidth / scale )

通过分析我们发现,安卓和IOS的适配规则殊途同归,可统一转换规则为:

function translateRule(dp) {        return dp * 750 / ( deviceWidth / scale );    }

到这里似乎大功告成,只要在写样式时祭出我们的法宝:计算属性,并动态赋到模板节点的style属性上即可。然而这种方式让开发同学想起了前端茹毛饮血的上古时代,而今前端显然已经沐浴在现代化的春风里很久了。如果在写样式的时候需要写固定尺寸时,能像native一样直接写pt/dp这样的单位那肯定是极好的。

扫了一下经过weex-loader编译的代码,与vue-loader编译的区别主要是在style的处理上,前者将style编译为map形式,并挂载到Vue实例上,所以我们在两个位置可以拿到编译后的style map

  1. vue实例生命周期内
  2. vue导出的组件对象上

由此有两个插入自动处理尺寸逻辑的方案:

  1. 运行时。于上述2的位置,扫描vue实例的style map,过滤出自定义单位和值并替换为weex识别的尺寸
  2. 编译时。通过webpack loader对vue文件进行预处理,扫描自定义单位并于1位置注入运行时处理尺寸的逻辑

分析

方案一:

  1. 性能较差,需要遍历每个页面整个组件树的style map
  2. vue实例拿到的style map,已被weex-loader过滤掉自定义单位,变成了人畜无害的数字。。。
  3. 需要js代码处理,一看就不是weex的亲儿子单位

结论:放弃

方案二:

  1. 每个组件单独注入修改尺寸的代码,免去了遍历组件树的开销
  2. 在weex-loader的样式分析之前解析,可以拿到原始样式代码
  3. 纯编译时纯工具处理,使用自定义单位如同使用原生单位一样方便,weex开发者毫无感知

结论:靠谱

实现

主流程

  • 识别style里的自定义单位/函数,抽取单位前的数值
  • 根据规则生成尺寸处理逻辑的代码
  • 注入到vue实例的beforeCreate函数里

    样式识别支持less和css

单位一般用于单参数映射规则,多参数映射规则可写成函数

规则文件

基于以下原因,需要独立的、用户自定义的、vue实例里可以方便引用的规则文件

  • 可能需要多个单位,因此需要一个规则集合
  • 规则需要支持自定义,方便使用者修改和扩展
  • 用户可能也需要手动调用某个单位的计算规则,比如实现动画

    loader实现内部提供了一个默认的规则文件,支持用户自定义规则文件去覆盖和扩展默认规则

默认规则

单位/函数 描述
dp 模拟安卓dp单位, 兼容ios,与native布局尺寸相同
mq media query
vw 相对于屏幕宽度的百分比
vh 相对于屏幕高度的百分比

数据流图如下:

数据流图

效果

无痛使用

.class-name {        /*            自定义单位/处理函数dp, vw            多个参数可用函数形式,单参数建议用单位        */        width: 100dp;        height: 200vw;        font-size: dp(24, 750); //可直接用24dp,这里仅做例子    }

UI效果

  • 不同尺寸屏幕native组件和weex容器完美契合(贴图不是实际屏幕大小,所以5s布局尺寸看着比较大,仅做页面内native和weex的尺寸比较)

  • weex与native文字尺寸基本一致(由于weex安卓使用小数字号有问题,所以计算后的字号做了四舍五入取整,且字体也差异,所以效果还是稍微有点差异,但对比做适配前已经好很多了)

扩展

因为实现原理是编译时解析自定义样式函数,并插入运行时js代码。因此除了用于计算尺寸外,还可以计算其他依赖环境(比如屏幕尺寸、设备类型等)的样式,成为一个通用的weex css运行时处理工具。

当然更期待着weex原生支持各种布局单位,这才是康庄大道。

包地址:

转载地址:http://prosl.baihongyu.com/

你可能感兴趣的文章
自己动手写GC
查看>>
工作习惯沉淀
查看>>
安装redis
查看>>
python 10.19作业
查看>>
groupby以后取每组前n行
查看>>
js获取页面传过来的参数
查看>>
KVO和通知中心
查看>>
Master Nginx(1) - Installing Nginx and Third-Party Modules
查看>>
单向链表的有关操作(链式存储结构)
查看>>
本学期学习计划
查看>>
java面向对象
查看>>
Eclipse快捷键大全(转载)
查看>>
网络概述:TCP-IP协议
查看>>
[1127]图形打印 sdutOJ
查看>>
跟KingDZ学HTML5之十一 HTML5 Form 表单新元素
查看>>
《面向模式的软件体系结构3-资源管理模式》读书笔记(2)--- Lazy Acquisition模式...
查看>>
操作系统基础
查看>>
python压缩文件脚本
查看>>
Redis notes
查看>>
每天一道算法题(11)——栈的push、pop 序列
查看>>