迷你应用标记、样式、脚本和更新

标记语言

如前所述,迷你应用是使用 HTML 方言编写的,而不是使用纯 HTML。如果您曾处理过 Vue.js 文本插值和指令,就会立刻熟悉,但在此之前,XML 转换 (XSLT) 中就已有类似的概念。您可以在下面查看微信的 WXML 中的代码示例,但所有迷你应用平台(即支付宝的 AXML、百度的 Swan Element、字节跳动的 TTML(尽管开发者工具将其称为 Bxml))和快速应用的 HTML 都是一样的。与 Vue.js 一样,迷你应用的底层编程概念是 Model-View-ViewModel (MVVM)。

数据绑定

数据绑定对应于 Vue.js 的文本插值

<!-- wxml -->
<view>{{message}}</view>
// page.js
Page({
  data: {
    message: "Hello World!",
  },
});

列表呈现

列表呈现的运作方式类似于 Vue.js v-for 指令

<!-- wxml -->
<view wx:for="{{array}}">{{item}}</view>
// page.js
Page({
  data: {
    array: [1, 2, 3, 4, 5],
  },
});

按条件呈现

有条件呈现的工作方式与 Vue.js 的 v-if 指令类似。

<!-- wxml -->
<view wx:if="{{view == 'one'}}">One</view>
<view wx:elif="{{view == 'two'}}">Two</view>
<view wx:else="{{view == 'three'}}">Three</view>
// page.js
Page({
  data: {
    view: "three",
  },
});

模板

您可以通过链接到模板定义的 is 属性以声明方式使用 WXML 模板,而无需执行命令式克隆 HTML 模板的 content

<!-- wxml -->
<template name="person">
  <view>
    First Name: {{firstName}}, Last Name: {{lastName}}
  </view>
</template>
<template is="person" data="{{...personA}}"></template>
<template is="person" data="{{...personB}}"></template>
<template is="person" data="{{...personC}}"></template>
// page.js
Page({
  data: {
    personA: { firstName: "Alice", lastName: "Foo" },
    personB: { firstName: "Bob", lastName: "Bar" },
    personC: { firstName: "Charly", lastName: "Baz" },
  },
});

样式

样式是针对 CSS 的方言而设置。WeChat 的名称为 WXSS。对于支付宝,其 CSS 称为 ACSS;对于百度,其 CSS 称为 CSS;对于字节跳动,其 CSS 称为 TTSS。它们的共同之处在于,它们都使用自适应像素扩展 CSS。编写常规 CSS 时,开发者需要转换所有像素单位,以适应宽度和像素宽高比不同的不同移动设备屏幕。TTSS 支持将 rpx 作为其底层,这意味着迷你应用会接管开发者的工作,并根据指定的屏幕宽度 750rpx 代表开发者转换单位。例如,在屏幕宽度为 393px(设备像素比率为 2.75)的 Pixel 3a 手机上,使用 Chrome 开发者工具在实体设备上检查时,响应式 200rpx 会变为 104px(393px / 750rpx * 200rpx ≈ 104px)。在 Android 中,相同的概念称为密度无关像素

使用 Chrome 开发者工具检查一个采用 `200rpx` 指定的自适应像素内边距的视图,可以看到该视图在 Pixel 3a 设备上实际为 `104px`。
使用 Chrome 开发者工具检查 Pixel 3a 设备上的实际内边距。
/* app.wxss */
.container {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  padding: 200rpx 0; /* ← responsive pixels */
  box-sizing: border-box;
}

由于组件(详见后文)不使用 shadow DOM,因此在页面上声明的样式会延伸到所有组件。常见的样式表文件组织方式是为全局样式创建一个根样式表,并为迷你应用的每个页面创建单独的页面样式表。样式可以使用行为类似于 @import CSS at-rule 的 @import 规则导入。与在 HTML 中一样,样式也可以以内嵌方式声明,包括动态文本插值(请参阅前面)。

<view style="color:{{color}};" />

设计脚本

迷你应用支持 JavaScript 的“安全子集”,其中包括对使用类似 CommonJSRequireJS 的不同语法的模块的支持。无法通过 eval() 执行 JavaScript 代码,也无法使用 new Function() 创建任何函数。脚本执行上下文在设备上为 V8JavaScriptCore,在模拟器中为 V8 或 NW.js。通常可以使用 ES6 或更高版本语法编码,因为如果 build 目标操作系统是采用旧版 WebView 实现的操作系统(请参阅稍后),特定的开发者工具会自动将代码转译为 ES5。超级应用提供商的文档明确提及,其脚本语言与 JavaScript 不同,不能与之混淆。不过,这项声明主要仅涉及模块的运作方式,即它们尚不支持标准 ES 模块

前面所述,迷你应用编程概念是 Model-View-ViewModel (MVVM)。逻辑层和视图层在不同的线程中运行,这意味着界面不会被长时间运行的操作阻塞。从 Web 的角度来看,您可以将其视为在 Web Worker 中运行的脚本。

WeChat 的脚本语言称为 WXS,Alipay 的脚本语言称为 SJS,ByteDance 的脚本语言也称为 SJS。百度在提及自己的 JS 时,会使用 JS 一词。这些脚本需要使用特殊类型的代码(例如微信中的 <wxs>)进行包含。相比之下,Quick App 使用常规 <script> 标记和 ES6 JS 语法。

<wxs module="m1">
  var msg = "hello world";
  module.exports.message = msg;
</wxs>

<view>{{m1.message}}</view>

您还可以通过 src 属性加载模块,或通过 require() 导入模块。

// /pages/tools.wxs
var foo = "'hello world' from tools.wxs";
var bar = function (d) {
  return d;
};
module.exports = {
  FOO: foo,
  bar: bar,
};
module.exports.msg = "some msg";
<!-- page/index/index.wxml -->
<wxs src="./../tools.wxs" module="tools" />
<view>{{tools.msg}}</view>
<view>{{tools.bar(tools.FOO)}}</view>
// /pages/logic.wxs
var tools = require("./tools.wxs");

console.log(tools.FOO);
console.log(tools.bar("logic.wxs"));
console.log(tools.msg);

JavaScript 桥接 API

将迷你应用与操作系统连接的 JavaScript 桥梁让您能够使用操作系统功能(请参阅使用强大的功能)。它还提供了一些便捷方法。如需了解概览,您可以查看 WeChatAlipayBaiduByteDance快应用的不同 API。

功能检测非常简单,因为所有平台都提供(字面上就是这样称呼的)canIUse() 方法,其名称似乎受到网站 caniuse.com 的启发。例如,ByteDance 的 tt.canIUse() 允许对 API、方法、参数、选项、组件和属性进行支持检查。

// Testing if the `<swiper>` component is supported.
tt.canIUse("swiper");
// Testing if a particular field is supported.
tt.canIUse("request.success.data");

更新

迷你应用没有标准化的更新机制(关于可能的标准化的讨论)。所有迷你应用平台都有一个后端系统,迷你应用开发者可以上传其迷你应用的新版本。然后,超级应用会使用该后端系统检查和下载更新。某些超级应用完全在后台执行更新,迷你应用本身不会受到任何影响。其他超级应用则会让迷你应用本身拥有更多控制权。

下面几段将更详细地介绍 WeChat 的迷你应用更新机制,以此为复杂流程的示例。WeChat 会在以下两种情况下检查是否有可用更新:

  1. 只要微信在运行,就会定期检查最近用过的微应用是否有更新。如果找到更新,系统会下载该更新,并在用户下次冷启动微应用时同步应用该更新。当用户打开微应用时,如果微应用当前未运行,则会发生冷启动微应用的情况(微信会在微应用在后台运行 5 分钟后强制关闭该微应用)。
  2. 微信还会在迷你应用冷启动时检查更新。对于用户长时间未打开的迷你应用,系统会同步检查并下载更新。在更新下载期间,用户必须等待。下载完成后,系统会应用更新,并打开迷你应用。如果下载失败(例如,由于网络连接不佳),系统仍会打开迷你应用。对于用户最近打开过的迷你应用,系统会在后台异步下载任何潜在的更新,并在用户下次冷启动迷你应用时应用这些更新。

迷你应用可以使用 UpdateManager API 选择接收早期更新。它提供以下功能:

  • 在检查更新时通知迷你应用。 (onCheckForUpdate)
  • 在有可用更新下载完毕时通知迷你应用。 (onUpdateReady)
  • 在无法下载更新时通知迷你应用。 (onUpdateFailed)
  • 允许迷你版应用强制安装可用更新,以便重启该应用。 (applyUpdate)

WeChat 还在其后端系统中为迷你应用开发者提供了其他更新自定义选项: 1. 其中一种方式是,允许开发者为已安装特定最低版本的迷你应用的用户选择停用同步更新,并强制更新异步执行。 2. 另一种方法允许开发者设置迷你应用的最低版本要求。这样一来,如果从低于最低版本要求的版本进行异步更新,系统会在应用更新后强制重新加载迷你应用。如果更新下载失败,它还会阻止打开旧版迷你应用。

致谢

本文由 Joe MedleyKayce BasquesMilica MihajlijaAlan Kent 和 Keith Gu 审核。