我已经很长时间使用微信小程序进行开发了,并且我非常精通小程序的开发;但是作为追求技术的前端开发人员,仅掌握小程序的开发经验还不够。我们应该进一步理解实现背后的原理和相应的考虑因素,这些因素可以解释我们在开发过程中遇到的一些疑问,例如,为什么小程序无法操作dom,小程序为什么是Web技术渲染或本机技术?另一方面,渲染等也有助于我们的个人成长。
首先,我声明本文中查看小程序开发人员工具的源代码的方法仅供学习。
本文将从以下几个方面讨论小程序的实现原理
如何查看小程序开发人员工具源代码
让我们通过微信小程序开发人员工具的源代码来讨论小程序的基本实现原理。使用开发人员工具版本号State v1.02.1904090的源代码来监视小程序的实现思路。对于Mac用户,如何查看微信的源代码,请查看微信小程序开发|微信小程序开发人员工具的软件包内容,然后输入Contents / Resources / app.nw / js / core / index.js,将以下代码注释为查看开发情况作者工具呈现的代码。
// 打开 inspect 窗口if (nw.App.argv.indexOf('inspect') !== -1) {tools.openInspectWin()}
然后重新启动小程序开发人员工具,将显示以下左页,单击其中一个页面以查看视图层的dom结构,如右图所示。
小程序建筑设计
小程序的体系结构设计与网络技术仍然有些不同。它利用了网络技术的某些优势,同时摒弃了诸如体验之类的网络技术的不利方面。让我们通过问题的形式来讨论小程序架构中的一些设计要点。
1、小程序是否在同一线程中渲染?双线程机制
开发了小程序的每个人都知道小程序是双线程设计,即视图渲染和业务逻辑运行在不同的线程中。此设计主要是为了解决Web技术中的一个痛点:
网页开发渲染线程和脚本线程是互斥的。长时间运行的脚本可能会导致页面无响应或出现白屏,并且体验很差。
小程序为了获得更好的体验,页面的呈现线程和脚本线程被设计为分别在不同的线程中执行。具体实现:
这解决了长脚本阻止页面呈现的问题,但同时也带来了一些新问题:
开发人员工具使用Webview加载业务逻辑层的代码。尽管从属环境具有DOM和BOM API,但是为了保持一致性; 小程序所有模块都已本地化,因此它们无法访问这些api。这样,两个线程使用本机,开发人员工具使用后台websocket服务在两者之间传递消息。有关详细信息,请参阅官方网站地图:
2、小程序是网页渲染吗?界面渲染机制
页面呈现的主要方式有三种:
由于小程序的宿主环境为微信,因此不太可能使用纯本机渲染,否则所有小程序都需要与微信一起编码和发布。使用纯Web渲染似乎可行。它支持快速的在线更新,并且可以通过添加最新资源在本地呈现;但是,纯Web渲染在某些具有复杂交互的页面上可能会遇到一些性能问题。这是由于Web技术所致,UI渲染和JavaScript脚本执行在单个线程中执行,这很容易导致某些逻辑任务抢占UI渲染资源。因此小程序是在混合模式下渲染的,如官方网站所述:
界面主要由成熟的 Web 技术渲染,辅之以大量的接口提供丰富的客户端原生能力。同时,每个小程序页面都是用不同的WebView去渲染,这样可以提供更好的交互体验,更贴近原生体验,也避免了单个WebView的任务过于繁重。
由于使用了混合渲染,因此本机渲染可以用于页面渲染。在什么情况下会使用本机渲染?
答案是使用小程序提供的地图,视频,画布,文本区域和其他组件。有关页面中本机渲染的渲染原理,请参阅官方网站本机组件。但是在小程序开发人员工具中,本机组件是使用html标签模拟的。有关详细信息,请参见下一节中地图组件的渲染结果。
3、小程序是否使用Web html标签呈现?扩展器组件框架
如上所述,小程序主要由成熟的Web技术渲染。您可以直接使用html提供的标签(例如p和table)来组织页面吗?答案是不。主要注意事项:
因此,小程序无法直接使用html标签来呈现页面,它提供了10多个内置组件来聚合Web标签,并且提供了JavaScript沙箱环境来阻止js访问任何浏览器api。
由于小程序无法直接使用html标签来呈现页面,因此它提供的内置组件(例如view和cover-view)是否意味着它们最终将转换为html提供的内置标签以进行渲染?答案应该不是。让我们看下面的代码:
test
开发人员工具中上述代码的最终呈现元素如下:
可以看出,小程序提供的组件最终没有转换为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}
这里的定义是小程序的低级模块化方法之一,另一个是require方法;通过define定义模块,require是指通过define定义的模块。从上面小程序中对业务模块代码的封装可以看出:
您可以查看require定义的源代码。
在实际的微信环境中,业务逻辑层运行在JSCore中,它没有与浏览器相关的信息,并且无法访问dom;但是小程序开发人员工具使用webview来运行业务逻辑代码,它具有与dom相关的界面;因此通过上述沙盒环境,js不能统一操作dom。
企业代码无法访问dom,如何实现动态页面更新?
答案是使用像vue这样的MVVM框架的数据驱动思想,即将视图状态和视图绑定在一起。状态更改时,视图可以自动更改,因此您无需直接操纵dom。
使用虚拟dom技术专门实现视图的动态更新。我相信每个人都已经了解虚拟DOM。可能是这样的过程:
使用JS对象模拟DOM树->比较两个虚拟DOM树之间的差异->将差异应用于实际DOM树。
以下是官方网站的图片,用于说明视图的动态更新过程:
// wxml{{msg}}// jsdata: {msg: 'Hello World'}