抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

小程序与Web开发的区别和联系

联系:小程序使用的技术栈和核心语言和HTML/JS/CSS差不多,Web用户很容易小程序开发。

区别:

  1. 底层架构的区别:Web开发中,渲染线程和脚本线程是互斥的,因此长时间的脚本处理会导致页面失去响应。小程序则采用特有的双线程模型,但因此在JS中无法使用DOM API。
  2. 运行环境的区别:网页开发者需要面对的环境是各式各样的浏览器,PC 端需要面对 IE、Chrome、QQ浏览器等,在移动端需要面对Safari、Chrome以及 iOS、Android 系统中的各式 WebView 。而小程序开发过程中需要面对的是两大操作系统 iOS 和 Android 的微信客户端,以及用于辅助开发的小程序开发者工具。
  3. ​开发流程上的区别:网页开发者在开发网页的时候,只需要使用到浏览器,并且搭配上一些辅助工具或者编辑器即可。小程序的开发则有所不同,需要经过申请小程序帐号、安装小程序开发者工具、配置项目等等过程方可完成。
  4. 小程序的宿主环境可以为小程序提供额外的功能,如登录、支付。

小程序的运行环境

小程序的运行环境采用了双线程模型:

渲染和逻辑的分离

小程序的运行环境主要由逻辑层和渲染层组成。

  1. 渲染层的界面使用了WebView 进行渲染,每个页面都对应一个渲染线程。
  2. 逻辑层采用JsCore线程运行JS脚本,这是一个单独的线程。
  3. 两类线程的通信会经由微信客户端进行转发。
  4. 网络请求由微信客户端转发

数据驱动视图

一个页面往往需要维护一定量的状态。逻辑层可以通过 setData 来更新数据,同时通知渲染层更新页面。

这种模式对于性能上的影响:

  1. 由于进程通信开销,频繁调用setData可能会导致处理队列阻塞,界面渲染不及时而导致卡顿
  2. 单次 setData 数据过大将延长进程通信的时间

打开页面时,渲染层宿主环境会把WXML转化成对应的JS对象,当收到setData的更新时,会对比前后差异,把差异应用在原来的Dom树上,渲染出正确的UI界面。

事件的触发

渲染层不能直接响应页面,因此用户触发事件后,会经由微信客户端转发给逻辑层进行处理。

异常处理

异常处理分为两种方式:

  1. window.onError: 需要window对象

  2. try-catch: 不支持捕获全局的错误事件

  3. 对于渲染层,采用 window.onError 来捕获事件

  4. 对于逻辑层,则采用 try-catch 来包裹来处理

小程序双线程模型的优缺点

优点:

  1. 渲染线程和服务线程不是完全互斥的,因此一些费时的逻辑操作并不会影响页面的渲染。
  2. 微信客户端能够阻止不安全的行为。

缺点:

  1. 两类进程的通信增加了通信开销,因此相当多的操作是异步的。

对比其他两类方案

  1. 纯客户端原生技术(例如RN):CSS一些特性不支持,稳定性不够,一些不可预期的问题(如许可协议)。
  2. 纯Web技术:渲染线程和脚本线程是互斥的,会带来性能问题

小程序的组件机制

概述

Exparser是微信小程序的组件组织框架,它的实现类似于一个简化版的ShadowDOM。

在模型上,它的实现和ShadowDOM高度相似,但不依赖浏览器原生和其他的库。

在运行环境上,它即可以在逻辑层上运行,也可以在渲染层运行。

在性能上,它的是高效的。

在能力上,Exparser增加了其他的API来支持小程序的组件化编程。

自定义组件

Exparser接管了所有的自定义组件注册与实例化。

shadowTree和computedTree

  1. shadowTree是组件内部的节点树。
  2. computedTree是最后所合成页面的节点树。

自定义组件的事件冒泡

根据冒泡的范围,冒泡事件划分为在Shadow Tree上冒泡的事件和在Composed Tree上冒泡的事件。

如果在Shadow Tree上冒泡,则冒泡只经过这个组件Shadow Tree上的节点,这样可以有效控制事件冒泡经过的范围。

原生组件

实现方式

原生组件创建时,会形成一个 div 元素,作为占位符。然后读取原生组件的宽高和相对于页面的位置,并通知客户端在这块区域上渲染原生组件。

更新时,组件会通知客户端进行相应的调整。

优点

  1. 对于复杂的组件,原生方式能够有效减轻WebView 渲染的压力
  2. 原生的输入框组件能够更好地控制键盘
  3. 避开 setData、数据通信和重渲染流程,从而使渲染性能更好

缺点

  1. 无法裁剪原生组件,例如 overflow: hidden 都是无效的。
  2. 原生组件的层级会比所有在WebView层渲染的普通组件要高。所以不能被其他WebView的组件覆盖。但可以利用其他原生组件来覆盖。

参考

  1. 小程序官方文档:https://developers.weixin.qq.com/miniprogram/dev/framework/
  2. 微信和支付宝小程序原理概述:https://juejin.cn/post/6844903805675388942#heading-18

评论