1.组件框架 Exparser(内置组件、自定义组件)
WXML属性值传递是从父组件向子组件的基本通信方式,而事件系统是从子组件向父组件的基本通信方式。
事件可以分为冒泡事件和非冒泡事件。冒泡事件还可以划分为在Shadow Tree上冒泡的事件和在Composed Tree上冒泡的事件。如果在Shadow Tree上冒泡,则冒泡只会经过这个组件Shadow Tree上的节点,这样可以有效控制事件冒泡经过的范围。
//input-with-label的WXML
<label> <input /> <slot /> </label>
//页面WXML
<view> <input-with-label> <button /> </input-with-label> </view>
用上面的例子来说,当在 button 上触发一个事件时:
l 如果事件是非冒泡的,那只能在 button 上监听到事件;
l 如果事件是在 Shadow Tree 上冒泡的,那 button 、 input-with-label 、view 可以依次监听到事件;
l 如果事件是在 Composed Tree 上冒泡的,那 button 、 slot 、label 、 input-with-label 、 view 可以依次监听到事件。
2.原生组件(由客户端原生参与组件的渲染)
常见的原生组件:
video | 视频 | 是 | 播放视频 |
map | 地图 | 是 | 展示地图 |
canvas | 画布 | 是 | 提供一个可以自由绘图的区域 |
picker | 弹出式选择器 | 否 | 初始时没有界面,点击时弹出选择器 |
最主要的【限制】:一些CSS样式无法应用于原生组件,例如,不能在父级节点使用overflow:hidden来裁剪原生组件的显示区域;不能使用transformrotate让原生组件产生旋转等。
原生组件会浮于页面其他组件之上(相当于拥有正无穷大的z-index值)使其它组件不能覆盖在原生组件上展示。想要解决这个问题,可以考虑使用cover-view和cover-image组件。这两个组件也是原生组件,同样是脱离WebView的渲染流程外,而原生组件之间的层级就可以按照一定的规则控制。
3. 通信性能优化
页面初始化的时间大致由页面初始数据通信时间和初始渲染时间两部分构成。
初始渲染完毕后,视图层可以在开发者调用setData后执行界面更新。逻辑层还会将setData所设置的数据字段与data合并,使开发者可以用this.data读取到变更后的数据。
开发者在执行setData调用时,最好遵循以下原则:
1.不要过于频繁调用setData,应考虑将多次setData合并成一次setData调用;
2.数据通信的性能与数据量正相关,因而如果有一些数据字段不在界面中展示且数据结构比较复杂或包含长字符串,则不应使用setData来设置这些数据;
3.与界面渲染无关的数据最好不要设置在data中,可以考虑设置在page对象的其他字段下。
视图层将事件反馈给逻辑层时,通信的方向是从视图层到逻辑层。因为这个通信过程是异步的,会产生一定的延迟,延迟时间同样与传输的数据量正相关,数据量小于64KB时在30ms内。降低延迟时间的方法主要有两个:
- 去掉不必要的事件绑定(WXML中的bind和catch),从而减少通信的数据量和次数;
- 事件绑定时需要传输target和currentTarget的dataset,因而不要在节点的data前缀属性(data-XXX)中放置过大的数据。
优化策略可以归纳为三点:精简代码,降低WXML结构和JS代码的复杂性;合理使用setData调用,减少setData次数和数据量;必要时使用分包优化(app.json中subPackages)。
4. 原生组件通信
【非原生组件】在setData的数据通信流程中,数据从逻辑层经过native层转发,传入视图层的WebView,再经过一系列渲染步骤之后传入组件。
一些原生组件支持使用context来更新组件。而使用context时,数据从逻辑层传到native层后,直接传入组件中,这样可以显著降低传输延迟。