微信小程序-底层框架-开发文档学习笔记

查看更多学习笔记:GitHub:LoveEmiliaForever
微信小程序开发指南
微信小程序开发文档

双线程模型

小程序是基于双线程模型的,在这个模型中,小程序的逻辑层与渲染层分开在不同的线程运行

技术选型

在对小程序的架构设计时的要求只有一个,就是要快,包括要渲染快、加载快等
我们期望体验到的是只有很短暂的加载界面,在一个过渡动画之后可以马上看到小程序的主界面

渲染界面的技术
使用纯客户端原生技术或纯 Web 技术都有各自的缺点,那如果使用两者结合起来的 Hybrid 技术来渲染小程序,能否优于各自独立渲染的技术方案呢
最终,我们选择类似于微信 JSSDK 这样的 Hybrid 技术,即界面主要由成熟的 Web 技术渲染,辅之以大量的接口提供丰富的客户端原生能力
同时,每个小程序页面都是用不同的WebView去渲染,这样可以提供更好的交互体验,更贴近原生体验,也避免了单个WebView的任务过于繁重

管控与安全

基于Web 技术来渲染小程序是存在一些不可控因素和安全风险的,这是因为Web技术是非常开放灵活的
为了解决管控与安全问题,我们必须阻止开发者使用一些浏览器提供的,诸如跳转页面、操作DOM、动态执行脚本的开放性接口
要彻底解决这个问题,我们必须提供一个沙箱环境来运行开发者的JavaScript 代码

得益于客户端系统有JavaScript 的解释引擎(在iOS下是用内置的 JavaScriptCore框架,在安卓则是用腾讯x5内核提供的JsCore环境)
我们可以创建一个单独的线程去执行 JavaScript,在这个环境下执行的都是有关小程序业务逻辑的代码,也就是我们前面一直提到的逻辑层
而界面渲染相关的任务全都在WebView线程里执行,通过逻辑层代码去控制渲染哪些界面,那么这一层当然就是所谓的渲染层

天生的延时

小程序是基于双线程模型,那就意味着任何数据传递都是线程间的通信,也就是都会有一定的延时
由于这个原因,在小程序架构里,很多操作都会变成异步

异步会使得各部分的运行时序变得复杂一些
逻辑层与渲染层需要有一定的机制保证时序正确,这些工作在小程序框架里会处理好

除了逻辑层与渲染层之间的通信有延时,各层与客户端原生交互同样是有延时的
注册给逻辑层有关客户端能力的接口,实际上也是跟微信主线程之间的通信,同样意味着有延时
这也是大部分提供的接口都是异步的原因

组件系统

小程序的视图是在WebView里渲染的,那搭建视图的方式自然就需要用到HTML语言
我们设计一套组件框架——Exparser,基于这个框架,内置了一套组件,以涵盖小程序的基础功能,便于开发者快速搭建出任何界面
同时也提供了自定义组件的能力,开发者可以自行扩展更多的组件,以实现代码复用

Exparser框架

Exparser是微信小程序的组件组织框架,内置在小程序基础库中,为小程序的各种组件提供基础的支持
Exparser会维护整个页面的节点树相关信息,包括节点的属性、事件绑定等,相当于一个简化版的Shadow DOM实现
小程序中,所有节点树相关的操作都依赖于Exparser,包括WXML到页面最终节点树的构建、createSelectorQuery调用和自定义组件特性等

内置组件

基于Exparser框架,内置了一套组件,提供了视图容器类、表单类、导航类、媒体类、开放类等几十种组件
一般而言,我们会把一个组件内置到小程序框架里的一个重要原则是:这个组件是基础的

自定义组件

自定义组件是开发者可以自行扩充的组件,开发者可以将常用的节点树结构提取成自定义组件,实现代码复用

ShadowTree的概念
组件的节点树称为ShadowTree,即组件内部的实现
最终拼接成的页面节点树被称为Composed Tree,即将页面所有组件节点树合成之后的树
各个组件也将具有各自独立的逻辑空间,每个组件都分别拥有自己的独立的数据、setData调用

运行原理
在使用自定义组件的小程序页面中,Exparser将接管所有的自定义组件注册与实例化

  • 小程序基础库提供有Page和Component两个构造器
  • (以Component为例)小程序启动时,构造器会将开发者设置的properties、data、methods等定义段,写入Exparser的组件注册表中
  • 这个组件在被其它组件引用时,就可以根据这些注册信息来创建自定义组件的实例
  • Page构造器的大体运行流程与之相仿,每个页面有一个与之对应的组件,称为页面根组件

组件创建的过程大致有以下几个要点

  1. 根据组件注册信息,从组件原型上创建出组件节点的JS对象,即组件的this
  2. 将组件注册信息中的data 复制一份,作为组件数据,即this.data
  3. 将这份数据结合组件WXML,据此创建出Shadow Tree,由于Shadow Tree中可能引用有其他组件,因而这会递归触发其他组件创建过程
  4. 将ShadowTree拼接到Composed Tree上,并生成一些缓存数据用于优化组件更新性能
  5. 触发组件的created生命周期函数
  6. 如果不是页面根组件,需要根据组件节点上的属性定义,来设置组件的属性值
  7. 当组件实例被展示在页面上时,触发组件的attached 生命周期函数,如果Shadw Tree中有其他组件,也逐个触发它们的生命周期函数

组件间通信
不同组件实例间的通信有WXML属性值传递、事件系统、selectComponent和relations等方式
WXML属性值传递是从父组件向子组件的基本通信方式,而事件系统是从子组件向父组件的基本通信方式
在ShadowDOM体系中,冒泡事件还可以划分为在Shadow Tree上冒泡的事件和在Composed Tree上冒泡的事件
在自定义组件中使用triggerEvent触发事件时,可以指定事件的bubbles、composed和capturePhase属性,用于标注事件的冒泡性质

Component({
  methods: {
    helloEvent: function() {
      this.triggerEvent('hello', {}, {
        bubbles: true,      // 这是一个冒泡事件
        composed: true,     // 这个事件在Composed Tree 上冒泡
        capturePhase: false // 这个事件没有捕获阶段
      })
    }
  }
})

原生组件

在内置组件中,有一些组件较为特殊,它们并不完全在Exparser的渲染体系下,而是由客户端原生参与组件的渲染,这类组件我们称为原生组件

原生组件运行机制

  • 组件被创建,包括组件属性会依次赋值。
  • 组件被插入到DOM树里,浏览器内核会立即计算布局,此时我们可以读取出组件相对页面的位置(x, y坐标)、宽高。
  • 组件通知客户端,客户端在相同的位置上,根据宽高插入一块原生区域,之后客户端就在这块区域渲染界面
  • 当位置或宽高发生变化时,组件会通知客户端做相应的调整

原生组件在WebView这一层的渲染任务是很简单,只需要渲染一个占位元素,之后客户端在这块占位元素之上叠了一层原生界面
因此,原生组件的层级会比所有在WebView层渲染的普通组件要高

原生组件好处

  • 扩展Web的能力,比如像输入框组件(input, textarea)有更好地控制键盘的能力。
  • 体验更好,同时也减轻WebView的渲染工作
  • 绕过setData、数据通信和重渲染流程,使渲染性能更好

常见原生组件
在这里插入图片描述

交互比较复杂的原生组件都会提供context,用于直接操作组件

原生组件渲染限制

原生组件脱离在WebView渲染流程外,这带来了一些限制
一些CSS样式无法应用于原生组件
最为常见的问题是,原生组件会浮于页面其他组件之上(相当于拥有正无穷大的z-index值)使其它组件不能覆盖在原生组件上展示
可以考虑使用cover-view和cover-image组件。这两个组件也是原生组件,同样是脱离WebView的渲染流程外,而原生组件之间的层级就可以按照一定的规则控制

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值