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

标记语言

如前所述,迷你应用不是使用纯 HTML,而是使用 HTML 方言编写的。如果您处理过 Vue.js 文本插值和指令,会感觉非常自在,但之前在 XML 转换 (XSLT) 中就存在过类似的概念。您可以查看微信的 WXML 中的代码示例,但此概念适用于所有迷你应用平台,即支付宝的 AXML、百度的 Swan Element、ByteDance 的 TTML(尽管开发者工具将其命名为 Bxml)以及 Quick App 的 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 的方言。微信的名称为 WXSS。对于支付宝,其方言称为 ACSS,百度的简称为 CSS;对于 ByteDance 而言,其方言称为 TTSS。它们的共同之处在于它们使用自适应像素扩展 CSS。编写常规 CSS 时,开发者需要转换所有像素单位,以适应宽度和像素比不同的移动设备屏幕。TTSS 支持将 rpx 单元作为其底层层,这意味着迷你应用会接管开发者的工作,并根据 750rpx 的指定屏幕宽度代表开发者转换这些单元。例如,在屏幕宽度为 393px(设备像素比为 2.75)的 Pixel 3a 手机上,使用 Chrome 开发者工具检查时,自适应 200rpx 在真实设备上会变为 104px(393px / 750rpx * 200rpx ~ 104px)。在 Android 中,这一概念称为密度无关像素

使用 Chrome DevTools 检查自适应像素内边距使用 `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 规则(其行为类似于 @import CSS at 规则)导入样式。与在 HTML 中一样,样式也可以以内嵌方式进行声明,包括动态文本插值(请参阅上文)。

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

设计脚本

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

所述,迷你应用编程概念是 model-view-viewmodel (MVVM)。逻辑层和视图层在不同的线程上运行,这意味着界面不会因长时间运行的操作而被屏蔽。就网络而言,可以将脚本视为在 Web 工作器中运行的脚本。

微信的脚本语言叫做 WXS、支付宝的 SJS,以及字节跳动的 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 桥接,您可以使用操作系统功能(请参阅使用强大功能)。它还提供了多种便捷方法。如需简要了解,您可以查看WeChat支付宝百度ByteDance快捷应用的不同 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");

更新

迷你应用没有标准化更新机制(围绕潜在的标准化讨论)。 所有迷你应用平台都有一个后端系统,可让迷你应用开发者上传其迷你应用的新版本。然后,超级应用使用该后端系统检查和下载更新。一些超级应用完全在后台执行更新,而迷你应用本身不会以任何方式影响更新流程。其他超级应用可让您对迷你应用本身进行更多控制。

以下段落通过一个复杂流程的示例,更详细地介绍了微信迷你应用的更新机制。在以下两种情况下,微信会检查有无可用更新:

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

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

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

微信还在其后端系统中为迷你应用开发者提供了额外的更新自定义选项: 1. 一种方法是,为已安装特定最低版本的迷你应用的用户选择停用同步更新,而是强制更新采用异步方式。 2. 另一个选项可让开发者设置迷你应用的最低版本要求。这样一来,如果对低于所需最低版本的版本进行异步更新,系统会在应用更新后强制重新加载迷你应用。如果更新下载失败,它也无法打开旧版迷你应用。

致谢

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