用户
 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,登录网站

小程序社区 首页 教程 查看内容

小程序摸爬滚打之路

Rolan 2020-1-10 00:12

上面这张图相信接触过小程序的开发者多多少少都有看到过,小程序的渲染层和逻辑层分别由 2 个线程管理:视图层的界面使用了 WebView 进行渲染,逻辑层采用 JsCore 线程运行 JS脚本。那么为什么要这样设计呢,为了管 ...

上面这张图相信接触过小程序的开发者多多少少都有看到过,小程序的渲染层和逻辑层分别由 2 个线程管理:视图层的界面使用了 WebView 进行渲染,逻辑层采用 JsCore 线程运行 JS脚本。

那么为什么要这样设计呢,为了管控和安全,我们需要阻止开发者使用一些,例如浏览器的window对象,跳转页面、操作DOM、动态执行脚本的开放性接口。

我们可以使用客户端系统的 JavaScript 引擎,iOS 下的 JavaScriptCore 框架,安卓下腾讯 x5 内核提供的 JsCore 环境。

这个沙箱环境只提供纯 JavaScript 的解释执行环境,没有任何浏览器相关接口。

2.双线程之间的通信

既然小程序的模型是双线程模型,那么是如何实现双线程之间的通信呢,由上图可以看出,逻辑层和视图层是通过Native层来进行转发的,这也就是说,我们可以把 DOM 的更新通过简单的数据通信来实现,类似于虚拟DOM的实现,用JS对象模拟DOM树,然后进行diff,然后把差异在视图层进行渲染,这一系列在Native之间的转化则由小程序的基础库来完成。

3.组件系统--Exparser框架

Exparser是微信小程序的组件组织框架,内置在小程序基础库中,为小程序的各种组件提供基础的支持。小程序内的所有组件,包括内置组件和自定义组件,都由Exparser组织管理。

  • DOM模型:模型上与WebComponents的ShadowDOM高度相似,但不依赖浏览器的原生支持,也没有其他依赖库;实现时,还针对性地增加了其他API以支持小程序组件编程。
  • 可在纯JS环境中运行:这意味着逻辑层也具有一定的组件树组织能力。
  • 高效轻量:性能表现好,在组件实例极多的环境下表现尤其优异,同时代码尺寸也较小。

当前Web Component已经支持局部作用域、slot插槽等等现有框架所提供的组件化方法,学习Web Component也是我接下来自己学习的目标之一 Orz 。

4.setData干了些什么

小程序的视图层目前使用 WebView 作为渲染载体,而逻辑层是由独立的 JavascriptCore 作为运行环境。在架构上,WebView 和 JavascriptCore 都是独立的模块,并不具备数据直接共享的通道。当前,视图层和逻辑层的数据传输,实际上通过两边提供的 evaluateJavascript 所实现。即用户传输的数据,需要将其转换为字符串形式传递,同时把转换后的数据内容拼接成一份 JS 脚本,再通过执行 JS 脚本的形式传递到两边独立环境。

而 evaluateJavascript 的执行会受很多方面的影响,数据到达视图层并不是实时的。

5.运行机制

小程序启动会有两种情况,一种是「冷启动」,一种是「热启动」。假如用户已经打开过某小程序,然后在一定时间内再次打开该小程序,此时无需重新启动,只需将后台状态的小程序切换到前台,这个过程就是热启动;冷启动指的是用户首次打开或小程序被微信主动销毁后再次打开的情况,此时小程序需要重新加载启动。

小程序开发日常问题

1.wx.request()的promise化

小程序框架自带的网络请求和Ajax请求非常相似都是异步请求,请求参数中需要送入url、method、data、header等参数,还要设置success成功的回调函数和fail失败的回调函数,如下图所示

通过回调函数处理就很容易造成回调地狱,所以Promise化还是很有必要的

class request {
  constructor() {
    this._baseUrl = 'https://xxx.com/api';
    this._token = wx.getStorageSync('token');
    this._header = {}
  }

  /**
   * GET类型的网络请求
   */
  getRequest(url, data, header = this._header) {
    return this.requestAll(url, data, header, 'GET')
  }

  /**
   * DELETE类型的网络请求
   */
  deleteRequest(url, data, header = this._header) {
    return this.requestAll(url, data, header, 'DELETE')
  }

  /**
   * PUT类型的网络请求
   */
  putRequest(url, data, header = this._header) {
    return this.requestAll(url, data, header, 'PUT')
  }

  /**
   * POST类型的网络请求
   */
  postRequest(url, data, header = this._header) {
    return this.requestAll(url, data, header, 'POST')
  }
  
  requestAll(url, data, header, method) {
    return new Promise((resolve, reject) => {
      wx.request({
        url: this._baseUrl + url,
        data: data,
        header: header,
        method: method,
        success: (res => {
          if (res.statusCode === 200) {
            resolve(res)
          } else {
            //其它错误,提示用户错误信息
            reject(res)
          }
        }),
        fail: (res => {
          reject(res)
        })
      })
    })
  }
}

export default request
复制代码

2.小程序的WXS

在小程序的日常开发中大家肯定会遇到需要对数据进行过滤转义的场景,而微信小程序没有像Vue一样的filter过滤器功能,大多数人会在渲染之前对数据进行一次清洗,而WXS就是为了解决这一痛点

什么是WXS

  • 是小程序出的一套脚本语言,用于 wxml 模板文件中,在模板文件中可以完成页面的结构。
  • 不依赖于运行时的基础库脚本,可以在所有版本的小程序中运行。
  • WXS 中不能调用 javascript 中定义的函数或者变量,也不能调用小程序提供的 API,他的运行环境和 javascript 是隔离的。
  • 小程序的条件渲染和循环渲染对 WXS 是无效的,就是说如果 WXS 代码包裹在未渲染的代码中,只要渲染的 wxml 部分调用了此模块,此段 WXS 代码依然会被加载。
  • 由于运行环境的差异,在 ios 设备上小程序的 WXS 会比 javascript 快 2~20 倍,在 android 设备上运行效率无异。
  • 模块想要暴露自己的私有变量和方法,只能通过 module.exports 实现。 若在模块中想要引用其他模块,只能通过 require 实现。
  • 只能使用 var 来定义变量,表现形式和 javascript 一样,会有变量提升。
  • WXS 模块只能在定义模块的 wxml 文件中被访问到,使用 或 时,WXS 模块不会被引入到对应的 wxml 文件中。
  • 不能使用 new Date() 应该使用 getDate() 。

WXS最常见的用处可能就是实现一个过滤器,如下所示

<wxs module="filter">
    function getFullPath(url) {
        return "https://shiyuanjieyi.cn" + url
    }
    module.exports.getFullPath = getFullPath
</wxs>
<image src="{{filter.getFullPath(url)}}"></image>
复制代码
鲜花
鲜花 (1)
鸡蛋
鸡蛋

刚表态过的朋友 (1 人)

分享至 : QQ空间
收藏
原作者: 我切图贼快 来自: 掘金