从微信小程序开发者工具源码看小程序架构设计实现原理( 二 )


答案是使用到小程序提供的map、video、canvas、textarea等组件,页面中原生渲染的渲染原理可以参考官网原生组件 。但是在小程序开发者工具中原生组件是使用html标签来模拟实现的 。具体可以看下一节的map组件渲染结果 。
3、小程序是用web的html标签渲染吗?Exparser组件框架
上面说到小程序主要由成熟的web技术渲染,能否直接使用html提供的标签如div、table等组织页面呢,答案不可以 。主要考量:

  • 管控与安全:web技术可以通过脚本获取修改页面敏感内容或者随意跳转其它页面
  • 能力有限,会限制小程序的表现形式
  • 标签众多,增加理解成本
所以,小程序不能直接使用html标签渲染页面,其提供了10多个内置组件来收敛web标签,并且提供一个JavaScript沙箱环境来避免js访问任何浏览器api 。
既然小程序不能直接使用html标签来渲染页面,那它提供的如view、cover-view等内置组件是否意味着最终都转换为html提供的内置标签来渲染呢?答案当不是 。我们来看如下代码:
<view class="map-container"> <map latitude='39.9088230000' style="height: 100%; width:100%;" longitude='116.3974700000' scale='16' id="id" bindregionchange="onRegionChange"></map> <view catchtap="onTap">test</view></view>上面代码在开发者工具中最终渲染元素如下图:
从微信小程序开发者工具源码看小程序架构设计实现原理

文章插图
 
可以看出,小程序提供的组件并没有最终转换为为html对应的标签来渲染,而是使用自定义的元素来渲染 。这些内置组件都是由Exparser框架负责管理,它内置在小程序基础库中,为小程序的各种组件提供基础的支持 。
Exparser框架基于Shadow DOM模型,模型上与WebComponents的ShadowDOM高度相似,具体可以参考官网组件系统 。内置组件创建方式如下:
从微信小程序开发者工具源码看小程序架构设计实现原理

文章插图
 
4、小程序可以操作dom吗?数据驱动
小程序为了管控与安全,提供一个JavaScript沙箱环境来运行JavaScript代码,js代码不能访问任何浏览器相关的接口,那就意味着js是不能操作dom和bom的,否则可能报错 。小程序实现沙箱环境呢?即通过将业务逻辑封装到一个局部环境中,局部环境修改dom和bom的相关api指向 。具体封装如下:
define("pages/xx/xxx.js", function(require, module, exports, window,document,frames,self,location,navigator,localStorage,history,Caches,screen,alert,confirm,prompt,fetch,XMLHttpRequest,WebSocket,webkit,WeixinJSCore,Reporter,print,URL,DOMParser,upload,preview,build,showDecryptedInfo,syncMessage,checkProxy,showSystemInfo,openVendor,openToolsLog,showRequestInfo,help,showDebugInfoTable,closeDebug,showDebugInfo,__global,WeixinJSBridge){'use strict'; // your code here}这里的define是小程序底层实现模块化的方法之一,还有一个是require方法;通过define来定义一个模块,require来引用一个define定义的模块 。从上面小程序对业务模块代码的封装可以看出:
  • define定义的模块对传递了跟浏览器相关的接口同名的API,如window、document、localStroage等等
  • require在引用模块时只传递require、module、exports三个参数,那么其他参数值就为undefined,不能在业务代码中访问这些接口
可以看看require定义的源码:
从微信小程序开发者工具源码看小程序架构设计实现原理

文章插图
 
在实际的微信环境,业务逻辑层运行在JSCore中,其没有浏览器相关的信息,访问dom无从谈起;但是小程序开发者工具使用webview来运行业务逻辑代码,它有dom相关接口;所以通过上面沙箱环境来统一使js无法操作dom 。
业务代码无法访问dom,怎么实现页面动态更新呢?
答案就是采用类vue这种MVVM框架的数据驱动思想,即让视图状态和视图绑定在一起,状态变更时,视图也能自动变更,这样就不用直接操作dom 。
视图的动态更新具体是采用virtual dom技术实现,virtual DOM相信大家都已有了解,大概是这么个过程:
用JS对象模拟DOM树 -> 比较两棵虚拟DOM树的差异 -> 把差异应用到真正的DOM树上 。
下面以官网的一幅图来说视图动态更新的过程:
// wxml <view>{{msg}}</view>// jsdata: { msg: 'Hello World'}
从微信小程序开发者工具源码看小程序架构设计实现原理

文章插图
 




推荐阅读