纯净、安全、绿色的下载网站

首页|软件分类|下载排行|最新软件|IT学院

当前位置:首页IT学院IT技术

从小程序开发者工具源码看原理实现 解析从小程序开发者工具源码看原理实现

lsgxeva   2021-06-09 我要评论
想了解解析从小程序开发者工具源码看原理实现的相关内容吗lsgxeva在本文为您仔细讲解从小程序开发者工具源码看原理实现的相关知识和一些Code实例欢迎阅读和指正我们先划重点:小程序,实现原理下面大家一起来学习吧

如何查看小程序开发者工具源码

下面我们通过微信小程序开发者工具的源码来说说小程序的底层实现原理以开发者工具版本号State v1.02.1904090的源码来窥探小程序的实现思路如何查看微信源码对于mac用户而言查看微信小程序开发者工具的包内容然后进入Contents/Resources/app.nw/js/core/index.js注释掉如下代码就可以查看开发者工具渲染后的代码

// 打开 inspect 窗口
if (nw.App.argv.indexOf('inspect') !== -1) {
    tools.openInspectWin()
}

然后重启小程序开发者工具就出现如下左侧页面点击其中一个页面就能看到view层的dom结构如下图右侧

小程序架构设计

1、小程序渲染是在同一个线程吗?双线程机制

开发过小程序的都知道小程序是双线程设计即视图渲染与业务逻辑分别在运行在不同的线程中这个设计主要是解决web技术中的一个痛点:

web页面开发渲染线程和脚本线程是互斥的长时间的脚本运行可能会导致页面失去响应或者白屏体验糟糕

小程序为了更好体验将页面的渲染线程和脚本线程分开设计在不同线程中执行具体实现:

  • 视图view层在webview中渲染一个页面对应一个webview
  • 业务逻辑Appservice层运行在同一个JSCore线程中具体ios是JavaScriptCoreandroid是X5 JSCore开发者工具是webview中

这样解决了长时间的脚本阻塞页面渲染的情况但是也带来一些新的问题:

  • 天生的延迟线程间要通信
  • 业务逻辑层因为运行在JSCore中无法访问DOM和BOM的api

开发者工具使用webview加载业务逻辑层的代码虽然依赖的环境有DOM和BOM api为了保持一致小程序对所有的模块进行了局部化处理使其不能访问这些api这样双线程通过native开发者工具通过后台websocket服务充当二者消息中转媒介并且提供一些基础功能具体可以参考官网图:

2、小程序是web渲染吗?界面渲染机制

页面渲染的方式主要有三种:

  • 纯web渲染
  • 纯native原生渲染
  • Hybrid渲染即web和native渲染结合

因为小程序的宿主环境是微信不太可能使用纯native渲染否则所有小程序需要跟微信一起编码发版采用纯web渲染貌似是可行的支持快速在线更新通过加装最新资源到本地即可渲染但是纯web渲染在一些有复杂交互的页面上可能会面临一些性能问题这是因为在web技术中UI渲染跟 JavaScript 的脚本执行都在一个单线程中执行这就容易导致一些逻辑任务抢占UI渲染的资源所以小程序采用Hybrid方式渲染用官网的描述如下:

界面主要由成熟的 Web 技术渲染辅之以大量的接口提供丰富的客户端原生能力

同时每个小程序页面都是用不同的WebView去渲染这样可以提供更好的交互体验更贴近原生体验也避免了单个WebView的任务过于繁重

既然采用Hybrid方式渲染那么页面的渲染可能会用到原生native来渲染什么情况会用到原生渲染呢?

答案是使用到小程序提供的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高度相似具体可以参考官网组件系统
内置组件的命名规范都是以wx-开头的外部引用内置组件如view最终会调用底层的wx-view组件Exparser的view组件创建方式如下:

4、小程序可以操作dom吗?数据驱动

小程序为了管控与安全提供一个JavaScript沙箱环境来运行JavaScript代码js代码不能访问任何浏览器相关的接口那就意味着js是不能操作dom和bom的否则可能报错小程序实现沙箱环境呢?即通过将业务逻辑封装到一个局部环境中局部环境修改dom和bom的相关api指向具体封装形式如下:

那么问题来了小程序是怎么给业务代码加上以上封装的呢?其实很简单在小程序开发者工具中有一个后台服务访问小程序的每个模块的path时后台服务会调用wrapSourceCodeInDefine方法将请求的JS文件的内容分别包裹在define域中方法的代码如下图所示:

这里的define是小程序底层实现模块化的方法之一还有一个是require方法通过define来定义一个模块require来引用一个define定义的模块从上面小程序对业务模块代码的封装可以看出:

define定义的模块对传递了跟浏览器相关的接口同名的API如window、document、localStroage等等
可能有人会说通过Function('return this')()来访问全局作用域window对象但是小程序堵死了这条路重写了Functioneval重置为undefined例如下图:

require在引用模块时只传递require、module、exports三个参数那么其他参数值就为undefined不能在业务代码中访问这些接口

可以看看require定义的源码:

在实际的微信环境业务逻辑层运行在JSCore中其没有浏览器相关的信息访问dom无从谈起但是小程序开发者工具使用webview来运行业务逻辑代码它有dom相关接口所以通过上面沙箱环境来统一使js无法操作dom

业务代码无法访问dom怎么实现页面动态更新呢?

答案就是采用类vue这种MVVM框架的数据驱动思想即让视图状态和视图绑定在一起状态变更时视图也能自动变更这样就不用直接操作dom

视图的动态更新具体是采用virtual dom技术实现virtual DOM相信大家都已有了解大概是这么个过程如下图:

实际处理可以简单描述如下:

用JS对象模拟DOM树 -> 比较两棵虚拟DOM树的差异 -> 把差异应用到真正的DOM树上

其中virtual dom是通过内置的wcc可以将wxml转换为js对象形式以此来表示DOM树结构

下面以官网的一幅图来说视图动态更新的过程:

// wxml
 <view>{{msg}}</view>

// js
data: {
   msg: 'Hello World'
}

上面说明了视图如何更新的其实在数据响应的过程中还有最重要的一环即业务逻辑层的如何将变化的数据同步到视图层呢这就涉及到双线程的通信了

5、小程序基础库作用到底是什么?

我们在开发者工具开发小程序时一般都会选择一个基础库如小程序开发者工具选择界面:

小程序基础库是用JavaScript写的但是我们并没有在我们的小程序中直接引用那么我们是怎么使用基础库提供功能的呢?答案是:

微信宿主环境会提前内置基础库打开小程序时会自动将基础库注入到小程序的视图层和业务逻辑层中小程序开发者工具则是由底层HTTP服务负责注入

下图是小程序底层HTTP服务通过script脚本注入的相关代码:

小程序基础库功能包括两个部分视图层的WAWebview.js和业务逻辑层的WAService.js下面就简单说下对应功能:

WAService为业务逻辑层提供基础功能

下看看一下WAService.js源码内容缩略图:

从源码可以看出基础库提供的WAService.js有很多功能主要包括以下几部分

  • WeixinJSBridge:消息通信的统一封装易于调用主要微信环境与native开发环境与开发者工具后台服务的通信
  • wx: wx对象下面的api方法封装
  • appServiceEngine:定义了全局的方法如definerequire, AppPageComponentgetAppgetCurrentPages等
  • virtualDOM: VirtualDOMDiff和Render UI实现
  • expraser: expraser框架组件的方法定义这意味着逻辑层也具有一定的组件树组织能力
  • Reporter: 小程序日志组件

WAWebview为视图层提供基础功能

小程序基础库为视图层提供的基础功能有些与WAService相同主要功能如下:

  • 消息通信封装为WeixinJSBridge
  • 日志组件Reporter封装
  • wx对象下的api跟WAService里的不同的是其大部分都是处理UI显示相关的方法
  • 小程序Expraser组件框架的实现和内置组件的注册
  • VirtualDOMDiff和Render UI实现
  • 定义页面相关事件触发

相关文章

猜您喜欢

  • Springboot整合@Async线程池 Springboot 怎样使用@Async整合线程池

    想了解Springboot 怎样使用@Async整合线程池的相关内容吗赵雷-Nathanial在本文为您仔细讲解Springboot整合@Async线程池的相关知识和一些Code实例欢迎阅读和指正我们先划重点:Springboot线程池,@Async整合线程池下面大家一起来学习吧..
  • JS内存空间 详解JS内存空间

    想了解详解JS内存空间的相关内容吗lsgxeva在本文为您仔细讲解JS内存空间的相关知识和一些Code实例欢迎阅读和指正我们先划重点:JS,内存空间下面大家一起来学习吧..

网友评论

Copyright 2020 www.fresh-weather.com 【世纪下载站】 版权所有 软件发布

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 点此查看联系方式