小程序组件

Web components

Web components 最初的承诺是让开发者可以将它们组合在一起,并在其基础上构建出色的应用。这种原子组件的例子包括 GitHub 的 time-elements、Stefan Judis 的 web-vitals-element,或者,请允许我自卖自夸一下,Google 的 dark mode toggle。然而,当涉及到完整的设计系统时,我观察到人们更喜欢依赖同一供应商提供的一组连贯的组件。不完全的例子列表包括 SAP 的 UI5 Web ComponentsPolymer ElementsVaadin's elements、Microsoft 的 FASTMaterial Web Components,以及可以说 AMP components 等等。然而,由于本文范围之外的许多因素,许多开发者也涌向了 ReactVue.jsEmber.js 等框架。超级应用提供商并没有让开发者可以自由地从这些选项中进行选择(或者,取决于您的观点,是迫使他们做出技术选择),而是普遍提供了一组开发者必须使用的组件。

小程序中的组件

您可以将这些组件视为上面提到的任何组件库。要了解可用组件的概况,您可以浏览 微信的组件库字节跳动的组件支付宝的组件百度的组件快应用的组件

之前,我展示了,虽然例如微信的 <image> 在底层是一个 Web component,但并非所有这些组件在技术上都是 Web component。有些组件,例如 <map><video>,被渲染为 操作系统内置组件,这些组件被分层在 WebView 之上。对于开发者来说,这个实现细节并没有被揭示,它们的编程方式与其他任何组件一样。

与往常一样,细节各不相同,但所有超级应用提供商的总体编程概念是相同的。一个重要的概念是数据绑定,正如之前在 标记语言 中所示。通常,组件按功能分组,因此更容易找到适合工作的组件。以下是支付宝分类的一个示例,它与其他供应商的组件分组类似。

  • 视图容器
    • view
    • swiper
    • scroll-view
    • cover-view
    • cover-image
    • movable-view
    • movable-area
  • 基本内容
    • text
    • icon
    • progress
    • rich-text
  • 表单组件
    • button
    • form
    • label
    • input
    • textarea
    • radio
    • radio-group
    • checkbox
    • checkbox-group
    • switch
    • slider
    • picker-view
    • picker
  • 导航
    • navigator
  • 媒体组件
    • image
    • video
  • Canvas
    • canvas
  • Map
    • map
  • 开放组件
    • web-view
    • lifestyle
    • contact-button
  • 无障碍功能
    • aria-component

下面,您可以看到支付宝的 <image>a:for 指令(参见列表渲染)中的使用,该指令循环遍历 index.js 中提供的图像数据数组。

/* index.js */
Page({
  data: {
    array: [
      {
        mode: "scaleToFill",
        text: "scaleToFill",
      },
      {
        mode: "aspectFit",
        text: "aspectFit",
      },
    ],
    src: "https://images.example.com/sample.png",
  },
  imageError(e) {
    console.log("image", e.detail.errMsg);
  },
  onTap(e) {
    console.log("image tap", e);
  },
  imageLoad(e) {
    console.log("image", e);
  },
});
<!-- index.axml -->
<view class="page">
  <view class="page-section" a:for="{{array}}" a:for-item="item">
    <view class="page-section-demo" onTap="onTap">
      <image
        class="image"
        mode="{{item.mode}}"
        onTap="onTap"
        onError="imageError"
        onLoad="imageLoad"
        src="{{src}}"
        lazy-load="true"
        default-source="https://images.example.com/loading.png"
      />
    </view>
  </view>
</view>

请注意 item.modemode 属性、srcsrc 属性以及三个事件处理程序 onTaponErroronLoad 到同名函数的 数据绑定。正如 之前所示,<image> 标签在内部被转换为 <div>,其中包含图像最终尺寸的占位符、可选的懒加载、默认源等。

组件的可用配置选项都列在 文档 中。文档中嵌入的 带有模拟器的组件预览 使代码立即变得切实可行。

Alipay component documentation with embedded component preview, showing a code editor with simulator that shows the component rendered on a simulated iPhone 6.
带有嵌入式组件预览的支付宝组件文档。
Alipay component preview running in a separate browser tab showing a code editor with simulator that shows the component rendered on a simulated iPhone 6.
支付宝组件预览弹出到自己的标签页中。

每个组件还有一个二维码,可以使用支付宝应用程序扫描该二维码,在独立的最小示例中打开组件示例。

Alipay's `image` component previewed on a real device after scanning a QR code in the documentation.
在真实设备上,通过文档中的 二维码链接 后,支付宝 <image> 组件的预览。

开发者可以通过利用专有的 URI 方案 antdevtool-tiny://,从文档直接跳转到支付宝 DevTools IDE。这允许文档直接链接到要导入的小程序项目,因此开发者可以立即开始使用该组件。

自定义组件

除了使用供应商提供的组件外,开发者还可以创建自定义组件。微信 WeChat、字节跳动 ByteDance、支付宝 Alipay 和 百度 Baidu 以及 快应用 Quick App 都存在这个概念。例如,一个百度自定义组件由四个文件组成,这些文件必须位于同一文件夹中:custom.swancustom.csscustom.jscustom.json

custom.json 文件将文件夹内容表示为自定义组件。

{
  "component": true
}

custom.swan 文件包含标记,custom.css 文件包含 CSS。

<view class="name" bindtap="tap">{{name}} {{age}}</view>
.name {
  color: red;
}

custom.js 文件包含逻辑。组件生命周期函数为 attached()detached()created()ready()。组件还可以对页面生命周期事件做出反应,即 show()hide()

Component({
  properties: {
    name: {
      type: String,
      value: "swan",
    },
  },
  data: {
    age: 1,
  },
  methods: {
    tap: function () {},
  },
  lifetimes: {
    attached: function () {},
    detached: function () {},
    created: function () {},
    ready: function () {},
  },
  pageLifetimes: {
    show: function () {},
    hide: function () {},
  },
});

然后可以在 index.json 中导入自定义组件,导入的键决定了名称(此处为:"custom"),之后可以在 index.swan 中使用该自定义组件。

{
  "usingComponents": {
    "custom": "/components/custom/custom"
  }
}
<view>
  <custom name="swanapp"></custom>
</view>

鸣谢

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