在插件开发中,以下组件不能在插件页面中使用:
- 开放能力(open-type)为以下之一的 button:
- contact(打开客服会话)
- getPhoneNumber(获取用户手机号)
- getUserInfo(获取用户信息)
- open-data
- web-view
在插件开发中,以下组件不能在插件页面中使用:
插件可以调用的 API 与微信小程序不同,主要有两个区别:
wx 对象下)。有些接口虽然在插件中不能使用,但可以通过插件功能页来达到目的,请参考 插件功能页。
各接口在插件中的支持情况可以在各接口的文档中确认,接口文档中会有如 「本接口从基础库 2.1.0 起支持在微信小程序插件中使用」 的标识;如果没有标识,说明插件暂未支持,如果有需要的具体使用场景和需求,可以在开发者社区中反馈。
以下表格汇总了目前插件可以调用的 API 及其对应版本要求,但这份表格已经不再更新,是否可以使用,请以具体接口文档中的说明和真机表现为准。
| API | 最低版本 | 备注 |
|---|---|---|
| wx.arrayBufferToBase64 | ||
| wx.base64ToArrayBuffer |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.request | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.downloadFile | 1.9.6 | |
| wx.uploadFile | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.connectSocket | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.previewImage | 1.9.6 | |
| wx.chooseImage | 1.9.6 | |
| wx.getImageInfo | 1.9.6 | |
| wx.saveImageToPhotosAlbum | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.startRecord | 1.9.6 | |
| wx.stopRecord | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.createLivePlayerContext | 1.9.6 | |
| wx.createLivePusherContext | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.getRecorderManager | 1.9.94 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.pauseVoice | 1.9.6 | |
| wx.playVoice | 1.9.6 | |
| wx.stopVoice | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.onBackgroundAudioPlay | 1.9.6 | |
| wx.getBackgroundAudioPlayerState | 1.9.6 | |
| wx.onBackgroundAudioStop | 1.9.6 | |
| wx.stopBackgroundAudio | 1.9.6 | |
| wx.onBackgroundAudioPause | 1.9.6 | |
| wx.seekBackgroundAudio | 1.9.6 | |
| wx.playBackgroundAudio | 1.9.6 | |
| wx.pauseBackgroundAudio | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.getBackgroundAudioManager | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.createInnerAudioContext | 1.9.6 | |
| wx.createAudioContext | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.chooseVideo | 1.9.6 | |
| wx.saveVideoToPhotosAlbum | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.createVideoContext | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.createCameraContext | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.setStorage | 1.9.6 | |
| wx.getStorage | 1.9.6 | |
| wx.removeStorage | 1.9.6 | |
| wx.setStorageSync | 1.9.6 | |
| wx.getStorageSync | 1.9.6 | |
| wx.removeStorageSync | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.getLocation | 1.9.6 | |
| wx.chooseLocation | 1.9.6 | |
| wx.onLocationChange | 2.8.0 | |
| wx.offLocationChange | 2.9.1 | |
| wx.stopLocationUpdate | 2.8.0 | |
| wx.startLocationUpdate | 2.8.0 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.openLocation | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.createMapContext | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.getSystemInfoSync | 1.9.6 | |
| wx.getSystemInfo | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.setKeepScreenOn | 1.9.6 | |
| wx.setScreenBrightness | 1.9.6 | |
| wx.getScreenBrightness | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.onUserCaptureScreen | 1.9.6 | 仅限插件页面中调用 |
| wx.offUserCaptureScreen | 2.9.1 | 仅限插件页面中调用 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.vibrateLong | 1.9.6 | |
| wx.vibrateShort | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.addPhoneContact | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.sendHCEMessage | 2.1.0 | |
| wx.stopHCE | 2.1.0 | |
| wx.onHCEMessage | 2.1.0 | |
| wx.offHCEMessage | 2.9.1 | |
| wx.startHCE | 2.1.0 | |
| wx.getHCEState | 2.1.0 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.onNetworkStatusChange | 1.9.6 | |
| wx.offNetworkStatusChange | 2.9.1 | |
| wx.getNetworkType | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.startAccelerometer | 1.9.6 | |
| wx.stopAccelerometer | 1.9.6 | |
| wx.onAccelerometerChange | 1.9.6 | |
| wx.offAccelerometerChange | 2.9.1 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.startDeviceMotionListening | 2.9.1 | |
| wx.stopDeviceMotionListening | 2.9.1 | |
| wx.offDeviceMotionChange | 2.9.1 | |
| wx.onDeviceMotionChange | 2.9.1 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.startGyroscope | 2.9.1 | |
| wx.stopGyroscope | 2.9.1 | |
| wx.offGyroscopeChange | 2.9.1 | |
| wx.onGyroscopeChange | 2.9.1 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.onCompassChange | 1.9.6 | |
| wx.offCompassChange | 2.9.1 | |
| wx.stopCompass | 1.9.6 | |
| wx.startCompass | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.makePhoneCall | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.scanCode | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.setClipboardData | 1.9.6 | |
| wx.getClipboardData | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.writeBLECharacteristicValue | 1.9.6 | |
| wx.startBluetoothDevicesDiscovery | 1.9.6 | |
| wx.getConnectedBluetoothDevices | 1.9.6 | |
| wx.notifyBLECharacteristicValueChange | 1.9.6 | |
| wx.onBluetoothDeviceFound | 1.9.6 | |
| wx.offBluetoothDeviceFound | 2.9.1 | |
| wx.readBLECharacteristicValue | 1.9.6 | |
| wx.openBluetoothAdapter | 1.9.6 | |
| wx.getBLEDeviceCharacteristics | 1.9.6 | |
| wx.stopBluetoothDevicesDiscovery | 1.9.6 | |
| wx.onBLEConnectionStateChange | 1.9.6 | |
| wx.getBluetoothDevices | 1.9.6 | |
| wx.getBluetoothAdapterState | 1.9.6 | |
| wx.onBluetoothAdapterStateChange | 1.9.6 | |
| wx.offBluetoothAdapterStateChange | 2.9.1 | |
| wx.getBLEDeviceServices | 1.9.6 | |
| wx.onBLECharacteristicValueChange | 1.9.6 | |
| wx.offBLECharacteristicValueChange | 2.9.1 | |
| wx.createBLEConnection | 1.9.6 | |
| wx.closeBluetoothAdapter | 1.9.6 | |
| wx.closeBLEConnection | 1.9.6 | |
| wx.notifyBLECharacteristicValueChange | 1.9.6 | |
| wx.onBLEConnectionStateChange | 1.9.6 | |
| wx.offBLEConnectionStateChange | 2.9.1 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.getBeacons | 1.9.6 | |
| wx.startBeaconDiscovery | 1.9.6 | |
| wx.onBeaconServiceChange | 1.9.6 | |
| wx.offBeaconServiceChange | 2.9.1 | |
| wx.onBeaconUpdate | 1.9.6 | |
| wx.offBeaconUpdate | 2.9.1 | |
| wx.stopBeaconDiscovery | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.connectWifi | 2.9.1 | |
| wx.getConnectedWifi | 2.9.1 | |
| wx.getWifiList | 2.9.1 | |
| wx.offGetWifiList | 2.9.1 | |
| wx.offWifiConnected | 2.9.1 | |
| wx.onEvaluateWifi | 2.9.1 | |
| wx.onGetWifiList | 2.9.1 | |
| wx.onWifiConnected | 2.9.1 | |
| wx.presetWifiList | 2.9.1 | |
| wx.setWifiList | 2.9.1 | |
| wx.startWifi | 2.9.1 | |
| wx.stopWifi | 2.9.1 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.hideLoading | 1.9.6 | |
| wx.showActionSheet | 1.9.6 | |
| wx.showLoading | 1.9.6 | |
| wx.hideToast | 1.9.6 | |
| wx.showToast | 1.9.6 | |
| wx.showModal | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.showNavigationBarLoading | 2.1.0 | 仅限插件页面中调用 |
| wx.hideNavigationBarLoading | 2.1.0 | 仅限插件页面中调用 |
| wx.setNavigationBarColor | 2.1.0 | 仅限插件页面中调用 |
| wx.setNavigationBarTitle | 2.1.0 | 仅限插件页面中调用 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.setBackgroundColor | 2.4.0 | 仅限插件页面中调用 |
| wx.setBackgroundTextStyle | 2.4.0 | 仅限插件页面中调用 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.createSelectorQuery | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.createIntersectionObserver | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.navigateBack | 2.1.0 | 仅限插件页面中调用 |
| wx.navigateTo | 2.2.2 | 仅限插件页面中调用 |
| wx.redirectTo | 2.2.2 | 仅限插件页面中调用 |
| wx.switchTab | 2.3.1 | 仅限插件页面中调用 |
| wx.reLaunch | 2.3.1 | 仅限插件页面中调用 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.createAnimation | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.pageScrollTo | 2.1.0 | 仅限插件页面中调用 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.createOffscreenCanvas | 2.7.1 | |
| wx.canvasPutImageData | 1.9.6 | |
| wx.canvasToTempFilePath | 1.9.6 | |
| wx.createCanvasContext | 1.9.6 | |
| wx.canvasGetImageData | 1.9.6 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.stopPullDownRefresh | 2.1.0 | 仅限插件页面中调用 |
| wx.startPullDownRefresh | 2.1.0 | 仅限插件页面中调用 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.getAccountInfoSync | 2.2.2 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.hideShareMenu | 2.1.0 | 仅限插件页面中调用 |
| wx.getShareInfo | 2.1.0 | 仅限插件页面中调用 |
| wx.showShareMenu | 2.1.0 | 仅限微信小程序插件页面中调用 |
| wx.updateShareMenu | 2.1.0 | 仅限微信小程序插件页面中调用 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.getRealtimeLogManager | 2.16.0 |
| API | 最低版本 | 备注 |
|---|---|---|
| wx.getSetting | 2.6.3 | |
| wx.openSetting | 2.10.3 | |
| wx.reportAnalytics | 1.9.6 | 见下方备注 |
这一组接口仅限在用户信息功能页中获得用户授权之后调用。否则将返回 fail 。详见 用户信息功能页 。
| API | 最低版本 | 备注 |
|---|---|---|
| wx.login | 2.3.1 | |
| wx.getUserInfo | 2.3.1 |
在使用插件前,首先要在微信小程序管理后台首页的“微信小程序信息设置页-第三方设置-插件管理”中添加插件。开发者可登录微信小程序管理后台,通过 appid 查找插件并添加。如果插件无需申请,添加后可直接使用;否则需要申请并等待插件开发者通过后,方可在微信小程序中使用相应的插件。
使用插件前,使用者要在 app.json 中声明需要使用的插件,例如:
代码示例:
{
"plugins": {
"myPlugin": {
"version": "1.0.0",
"provider": "wxidxxxxxxxxxxxxxxxx"
}
}
}
如上例所示, plugins 定义段中可以包含多个插件声明,每个插件声明以一个使用者自定义的插件引用名作为标识,并指明插件的 appid 和需要使用的版本号。其中,引用名(如上例中的 myPlugin)由使用者自定义,无需和插件开发者保持一致或与开发者协调。在后续的插件使用中,该引用名将被用于表示该插件。
如果插件只在一个分包内用到,可以将插件仅放在这个分包内,例如:
{
"subpackages": [
{
"root": "packageA",
"pages": [
"pages/cat",
"pages/dog"
],
"plugins": {
"myPlugin": {
"version": "1.0.0",
"provider": "wxidxxxxxxxxxxxxxxxx"
}
}
}
]
}
在分包内使用插件有如下限制:
使用插件时,插件的代码对于使用者来说是不可见的。为了正确使用插件,使用者应查看插件详情页面中的“开发文档”一节,阅读由插件开发者提供的插件开发文档,通过文档来明确插件提供的自定义组件、页面名称及提供的 js 接口规范等。
使用插件提供的自定义组件,和 使用普通自定义组件 的方式相仿。在 json 文件定义需要引入的自定义组件时,使用 plugin:// 协议指明插件的引用名和自定义组件名,例如:
代码示例:
{
"usingComponents": {
"hello-component": "plugin://myPlugin/hello-component"
}
}
出于对插件的保护,插件提供的自定义组件在使用上有一定的限制:
this.selectComponent 接口无法获得插件的自定义组件实例对象,同样插件的 this.selectComponent 也无法获得微信小程序和其他插件的;
>>> 选择器无法选入插件内部。开发插件前,请阅读了解《微信小程序插件接入指南》 了解开通流程及开放范围,并开通插件功能。如果未开通插件功能,将无法上传插件。
插件类型的项目可以在开发者工具中直接创建。详情

新建插件类型的项目后,如果创建示例项目,则项目中将包含三个目录:
plugin 目录:插件代码目录。miniprogram 目录:放置一个微信小程序,用于调试插件。doc 目录:用于放置插件开发文档。miniprogram 目录内容可以当成普通微信小程序来编写,用于插件调试、预览和审核。下面的内容主要介绍 plugin 中的插件代码及 doc 中的插件开发文档。
我们提供了一个可以直接在微信开发者工具中查看的完整插件示例,开发者可以和本文互相对照以便理解。请注意:
miniprogram/app.json 中(如下图)使示例正常运行。
一个插件可以包含若干个自定义组件、页面,和一组 js 接口。插件的目录内容如下:
plugin
├── components
│ ├── hello-component.js // 插件提供的自定义组件(可以有多个)
│ ├── hello-component.json
│ ├── hello-component.wxml
│ └── hello-component.wxss
├── pages
│ ├── hello-page.js // 插件提供的页面(可以有多个,自微信小程序基础库版本 2.1.0 开始支持)
│ ├── hello-page.json
│ ├── hello-page.wxml
│ └── hello-page.wxss
├── index.js // 插件的 js 接口
└── plugin.json // 插件配置文件
向使用者微信小程序开放的所有自定义组件、页面和 js 接口都必须在插件配置文件 plugin.json 列出,格式如下:
代码示例:
{
"publicComponents": {
"hello-component": "components/hello-component"
},
"pages": {
"hello-page": "pages/hello-page"
},
"main": "index.js"
}
这个配置文件将向使用者微信小程序开放一个自定义组件 hello-component,一个页面 hello-page 和 index.js 下导出的所有 js 接口。
请注意:在插件开发中,只有部分接口可以直接调用;另外还有部分能力(如获取用户信息和发起支付等)可以通过插件功能页的方式使用。
插件可以定义若干个自定义组件,这些自定义组件都可以在插件内相互引用。但提供给使用者微信小程序使用的自定义组件必须在配置文件的 publicComponents 段中列出(参考上文)。
除去接口限制以外,自定义组件的编写和组织方式与一般的自定义组件相同,每个自定义组件由 wxml, wxss, js 和 json 四个文件组成。具体可以参考自定义组件的文档。
插件从微信小程序基础库版本 2.1.0 开始支持页面。插件可以定义若干个插件页面,可以从本插件的自定义组件、其他页面中跳转,或从使用者微信小程序中跳转。所有页面必须在配置文件的 pages 段中列出(参考上文)。
除去接口限制以外,插件的页面编写和组织方式与一般的页面相同,每个页面由 wxml, wxss, js 和 json 四个文件组成。具体可以参考其他关于页面的文档。
插件执行页面跳转的时候,可以使用 navigator 组件。当插件跳转到自身页面时,url 应设置为这样的形式:plugin-private://PLUGIN_APPID/PATH/TO/PAGE。需要跳转到其他插件时,也可以这样设置 url。
代码示例:
<navigator url="plugin-private://wxidxxxxxxxxxxxxxx/pages/hello-page">
Go to pages/hello-page!
</navigator>
自基础库版本 2.2.2 开始,在插件自身的页面中,插件还可以调用 wx.navigateTo 来进行页面跳转,url 格式与使用 navigator 组件时相仿。
插件可以在接口文件(在配置文件中指定,详情见上文)中 export 一些 js 接口,供插件的使用者调用,如:
代码示例:
module.exports = {
hello: function() {
console.log('Hello plugin!')
}
}
在开发者工具中预览效果,需要手动填写一下
miniprogram/app.json中的插件 AppID
从基础库 2.11.1 起,在插件中有全局函数 requireMiniProgram,可以获取由使用者微信小程序导出的内容。
例如,使用者微信小程序做了如下导出:
// 使用者微信小程序
module.exports = {
greeting() {
return 'Greetings from Weixin MiniProgram!';
}
}
那么在插件中,可以这样获得内容:
// 插件
const miniProgramExports = requireMiniProgram();
miniProgramExports.greeting(); // 'Greetings from Weixin MiniProgram!'
另外也可以参考使用者微信小程序的相关文档
在开发者工具中预览效果,需要手动填写一下
miniprogram/app.json中的插件 AppID
有时,插件可能需要在页面或者自定义组件中,将一部分区域交给使用的微信小程序来渲染,因此需要能够引用微信小程序的自定义组件。但由于插件中不能直接指定微信小程序的自定义组件路径,因此无法直接通过 usingComponents 的方式来引用。这里介绍通过抽象节点(generics)来实现引用的方式。
如果是插件自定义组件(例如 plugin-view),那么我们可以通过声明一个 generic:
// plugin/components/plugin-view.json
{ "componentGenerics": { "mp-view": true } }
并在希望显示微信小程序组件的位置引用:
<!-- plugin/components/plugin-view.wxml -->
<view>微信小程序组件:</view>
<mp-view /><!-- 这里是一个微信小程序自定义组件 -->
在微信小程序中引用 plugin-view 时,就可以传递组件给插件进行渲染了:
<!-- miniprogram/page/index.wxml -->
<plugin-view generic:mp-view="comp-from-miniprogram" />
如果是插件页,插件页本身就是一个页面顶层组件,微信小程序不会引用它,无法通过 generic:xxx="" 的方式来指定抽象节点实现;因此,从基础库 2.12.2 起,微信小程序可以在插件的配置里为插件页指定抽象节点实现。例如插件页面名为 plugin-index,则可以:
{
"myPlugin": {
"provider": "wxAPPID",
"version": "1.0.0",
"genericsImplementation": {
"plugin-index": {
"mp-view": "components/comp-from-miniprogram"
}
}
}
}
另外也可以参考使用者微信小程序的相关文档
插件可以像微信小程序一样预览和上传,但插件没有体验版。
插件会同时有多个线上版本,由使用插件的微信小程序决定具体使用的版本号。
手机预览和提审插件时,会使用一个特殊的微信小程序来套用项目中 miniprogram 文件夹下的微信小程序,从而预览插件。
appid、appsecret 并设置域名列表。appid。通常情况下,可以将 miniprogram 下的代码当做使用插件的微信小程序代码,来进行插件的调试和测试。
但有时,需要将插件的代码放在实际运行的微信小程序中进行调试、测试。此时,可以使用开发版的微信小程序直接引用开发版插件。方法如下:
"version": "dev-[开发版 ID]" 的形式,如 "version": "dev-abcdef0123456789abcdef0123456789" 即可。如果开发版微信小程序引用了开发版插件,此时这个微信小程序就不能上传发布了。必须要将插件版本设为正式版本之后,微信小程序才可以正常上传、发布。
注意事项:
在使用者微信小程序使用插件时,插件代码并不可见。因此,除了插件代码,我们还支持插件开发者上传一份插件开发文档。这份开发文档将展示在插件详情页,供其他开发者在浏览插件和使用插件时进行阅读和参考。插件开发者应在插件开发文档中对插件提供的自定义组件、页面、接口等进行必要的描述和解释,方便使用者微信小程序正确使用插件。
插件开发文档必须放置在插件项目根目录中的 doc 目录下,目录结构如下:
doc
├── README.md // 插件文档,应为 markdown 格式
└── picture.jpg // 其他资源文件,仅支持图片
其中,README.md 的编写有一定的 限制条件,具体来说:
编辑 README.md 之后,可以在开发者工具左侧资源管理器的文件栏中右键单击 README.md,并选择上传文档。发布上传文档后,文档不会立刻发布。此时可以使用账号和密码登录 管理后台 ,在 微信小程序插件 > 基本设置 中预览、发布插件文档。
插件文档总大小不能大于 2M,超过时上传将返回错误码 80051。
插件不能直接引用其他插件。但如果微信小程序引用了多个插件,插件之间是可以互相调用的。
一个插件调用另一个插件的方法,与插件调用自身的方法类似。可以使用 plugin-private://APPID 访问插件的自定义组件、页面(暂不能使用 plugin:// )。
对于 js 接口,可使用 requirePlugin ,但目前尚不能在文件一开头就使用 requirePlugin ,因为被依赖的插件可能还没有初始化,请考虑在更晚的时机调用 requirePlugin ,如接口被实际调用时、组件 attached 时。(未来会修复这个问题。)
插件在使用 wx.request 等 API 发送网络请求时,将会额外携带一个签名 HostSign ,用于验证请求来源于微信小程序插件。这个签名位于请求头中,形如:
X-WECHAT-HOSTSIGN: {"noncestr":"NONCESTR", "timestamp":"TIMESTAMP", "signature":"SIGNATURE"}
其中, NONCESTR 是一个随机字符串, TIMESTAMP 是生成这个随机字符串和 SIGNATURE 的 UNIX 时间戳。它们是用于计算签名 SIGNATRUE 的参数,签名算法为:
SIGNATURE = sha1([APPID, NONCESTR, TIMESTAMP, TOKEN].sort().join(''))
其中,APPID 是 所在微信小程序 的 AppId (可以从请求头的 referrer 中获得);TOKEN 是插件 Token,可以在微信小程序插件基本设置中找到。
网络请求的 referer 格式固定为 https://servicewechat.com/{appid}/{version}/page-frame.html,其中 {appid} 为微信小程序的 appid,{version} 为微信小程序的版本号,版本号为 0 表示为开发版、体验版以及审核版本,版本号为 devtools 表示为开发者工具,其余为正式版本。
插件开发者可以在服务器上按以下步骤校验签名:
sort 对 APPID NONCESTR TIMESTAMP TOKEN 四个值表示成字符串形式,按照字典序排序(同 JavaScript 数组的 sort 方法);join 将排好序的四个字符串直接连接在一起;sha1 算法,其结果即 SIGNATURE 。自基础库版本 2.0.7 开始,在微信小程序运行期间,若网络状况正常, NONCESTR 和 TIMESTAMP 会每 10 分钟变更一次。如有必要,可以通过判断 TIMESTAMP 来确定当前签名是否依旧有效。
插件的开发和使用自微信小程序基础库版本 1.9.6 开始支持。(如果插件包含页面,则需要基础库版本 2.1.0 。)
插件是对一组 js 接口、自定义组件 或页面的封装,用于嵌入到微信小程序中使用。插件不能独立运行,必须嵌入在其他微信小程序中才能被用户使用;而第三方微信小程序在使用插件时,也无法看到插件的代码。因此,插件适合用来封装自己的功能或服务,提供给第三方微信小程序进行展示和使用。
插件开发者可以像开发微信小程序一样编写一个插件并上传代码,在插件发布之后,其他微信小程序方可调用。微信小程序平台会托管插件代码,其他微信小程序调用时,上传的插件代码会随微信小程序一起下载运行。
相对于普通 js 文件或自定义组件,插件拥有更强的独立性,拥有独立的 API 接口、域名列表等,但同时会受到一些限制,如 一些 API 无法调用或功能受限。还有个别特殊的接口,虽然插件不能直接调用,但可以使用 插件功能页 来间接实现。
同时,框架会对微信小程序和微信小程序使用的每个插件进行数据安全保护,保证它们之间不能窃取其他任何一方的数据(除非数据被主动传递给另一方)。
对于插件开发者,请阅读 开发插件 章节;对于插件使用者,请阅读 使用插件 章节。
在 wxml 面板中可以查看自定义组件在渲染时的 Data 数据。
在 wxml 中先选中需要查看的自定义组件,然后切换到 Component Data 即可实时查看当前自定义组件的数据

基础库 2.11.2 及以上版本支持,2.11.2 以下和未配置的效果相同
在使用如 分包异步化 或 用时注入 等特性时,自定义组件所引用的其他自定义组件,在刚开始进行渲染时可能处于不可用的状态。此时,为了使渲染过程不被阻塞,不可用的自定义组件需要一个 「占位组件」(Component placeholder)。基础库会用占位组件替代不可用组件进行渲染,在该组件可用后再将占位组件替换回该组件。
一个自定义组件的占位组件可以是另一个自定义组件、或一个内置组件。
页面或自定义组件对应的 JSON 配置中的 componentPlaceholder 字段用于指定占位组件,如:
{
"usingComponents": {
"comp-a": "../comp/compA",
"comp-b": "../comp/compB",
"comp-c": "../comp/compC"
},
"componentPlaceholder": {
"comp-a": "view",
"comp-b": "comp-c"
}
}
该配置表示:
comp-a 的占位组件为内置组件 viewcomp-b 的占位组件为自定义组件 comp-c(其路径在 usingComponents 中配置)假设该配置对应的模板如下:
<button ontap="onTap">显示组件</button>
<comp-a wx-if="{{ visible }}">
<comp-b prop="{{ p }}">text in slot</comp-b>
</comp-a>
微信小程序启动时 visible 为 false,那么只有 button 会被渲染;点击按钮后,this.setData({ visible: true }) 被执行,此时如果 comp-a, comp-b 均不可用,则页面将被渲染为:
<button>显示组件</button>
<view>
<comp-c prop="{{ p }}">text in slot</comp-c>
</view>
comp-a 与 comp-b 准备完成后,页面被替换为:
<button>显示组件</button>
<comp-a>
<comp-b prop="{{ p }}">text in slot</comp-b>
</comp-a>
comp-c),为其指定占位组件是无效的。可以理解为如果一个组件需要作为其他组件的占位组件,则它必须在一开始就是可用的;基础库尝试渲染一个组件时,会首先递归检查 usingComponents,收集其将使用到的所有组件的信息;在这个过程中,如果某个被使用到的组件不可用,基础库会先检查其是否有对应的占位组件。如果没有,基础库会中断渲染并抛出错误;如果有,则会标记并在后续渲染流程中使用占位组件替换该不可用的组件进行渲染。不可用的组件会在当前渲染流程结束后尝试准备(下载分包或注入代码等);等到准备过程完成后,再尝试渲染该组件(实际上也是在执行这个流程),并替换掉之前渲染的占位组件。
基础库 2.12.0 开始支持,低版本需做兼容处理。
如果想要知道 setData 引发界面更新的开销,可以使用更新性能统计信息接口。它将返回每次更新中主要更新步骤发生的时间戳,可以用来大体上估计自定义组件(或页面)更新性能。例如:
Component({
attached() { // 调用时机不能早于 attached
this.setUpdatePerformanceListener({withDataPaths: true}, (res) => {
console.log(res)
})
}
})
setUpdatePerformanceListener 方法接受一个 options 对象和回调函数 listener 作为参数。
其中, options 对象包含以下字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| withDataPaths | Boolean | 是否返回变更的 data 字段信息 |
listeners 返回携带一个 res 对象,表示一次由 setData 引发的 更新过程 。根据 setData 调用时机的不同,更新过程大体可以分为三类:
updateProcessId ;updateProcessId ,但还有一个 parentUpdateProcessId ;每次成功的 setData 调用都会产生一个更新过程,使得 listener 回调一次。不过 setData 究竟触发了哪类更新过程很难判断,更新性能好坏与其具体是哪类更新也没有必然联系,只是它们的返回值参数有所不同。
res 中包含以下字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| updateProcessId | Number | 此次更新过程的 ID |
| parentUpdateProcessId | Number | 对于子更新,返回它所属的更新过程 ID |
| isMergedUpdate | Boolean | 是否是被合并更新,如果是,则 updateProcessId 表示被合并到的更新过程 ID |
| dataPaths | Array | 此次更新的 data 字段信息,只有 withDataPaths 设为 true 时才会返回 |
| pendingStartTimestamp | Number | 此次更新进入等待队列时的时间戳 |
| updateStartTimestamp | Number | 更新运算开始时的时间戳 |
| updateEndTimestamp | Number | 更新运算结束时的时间戳 |
说明:
setUpdatePerformanceListener 只会激活当前组件或页面的统计, parentUpdateProcessId 有可能是其他组件或者页面的更新过程 ID 而未被统计回调,如果想要知道页面内所有的更新过程,需要在所有组件中都调用 setUpdatePerformanceListener ;setUpdatePerformanceListener 时传入第二个参数 listener 为 null 即可。在编写高质量的自定义组件过程中,单元测试是永远避不开的一个话题。完善的测试用例是提高自定义组件可用性的保证,同时测试代码覆盖率也是必不可少的一个环节。微信小程序从基础库版本 2.2.1 开始拥抱开源,支持使用 npm 安装自定义组件,那针对自定义组件的单元测试也是必须支持的。
以下就来介绍如何对自定义组件进行单元测试。
现在市面上流行的测试框架均可使用,只要它能兼顾 nodejs 端和 dom 环境。因为我们需要依赖到 nodejs 的一些库来完善测试环境,同时 dom 环境也是必须的,因为我们需要建成完整的 dom 树结构,才能更好的模拟自定义组件的运行。例如可以选用 mocha + jsdom 的组合,亦可选用 jest,下述例子选用 jest 作为测试框架来说明。
微信小程序的运行环境比较特殊,不同于常见的浏览器环境,它采用的是双线程的架构。而在进行单元测试时,我们并不需要用到这样复杂的架构带来的利好,我们进行的是功能测试而无需苛求性能、安全等因素,因此我们提供了一个测试工具集以支持自定义组件在 nodejs 单线程中也能运行起来。
我们先安装一下测试工具集——miniprogram-simulate:
npm i --save-dev miniprogram-simulate
假设我们有如下自定义组件:
<!-- /components/index.wmxl -->
<view class="index">{{prop}}</view>
// /components/index.js
Component({
properties: {
prop: {
type: String,
value: 'index.properties'
},
},
})
/* /components/index.wxss */
.index {
color: green;
}
我们想要测试渲染的结果,可以按照如下方式编写测试用例:
// /test/components/index.test.js
const simulate = require('miniprogram-simulate')
test('components/index', () => {
const id = simulate.load('/components/index') // 此处必须传入绝对路径
const comp = simulate.render(id) // 渲染成自定义组件树实例
const parent = document.createElement('parent-wrapper') // 创建父亲节点
comp.attach(parent) // attach 到父亲节点上,此时会触发自定义组件的 attached 钩子
const view = comp.querySelector('.index') // 获取子组件 view
expect(view.dom.innerHTML).toBe('index.properties') // 测试渲染结果
expect(window.getComputedStyle(view.dom).color).toBe('green') // 测试渲染结果
})
PS:测试工具集中的 wx 对象和内置组件都不会实现真正的功能,如果需要测试一些特殊场景的话,可以自行覆盖掉测试工具集中的 api 接口和内置组件。
PS:目前因为有部分自定义组件功能仍未支持(如抽象节点等),故测试工具暂无法全部覆盖自定义组件的特性,后续会继续完善。
测试工具集中提供了一些方便测试的接口,比如:
更多详细的用法可以参阅 github 仓库上的文档。
微信小程序从基础库版本 2.2.1 开始支持使用 npm 安装第三方包,因此也支持开发和使用第三方自定义组件包。关于 npm 功能的详情可先阅读相关文档。
开发一个开源的自定义组件包给他人使用,首先需要明确他人是要如何使用这个包的,如果只是拷贝微信小程序目录下直接使用的话,可以跳过此文档。此文档中后续内容是以 npm 管理自定义组件包的前提下进行说明的。
在开发之前,要求开发者具有基础的 node.js 和 npm 相关的知识,同时需要准备好支持 npm 功能的开发者工具,点此下载。
为了方便开发者能够快速搭建好一个可用于开发、调试、测试的自定义组件包项目,官方提供了一个项目模板,下载使用模板的方式有三种:
项目模板中的构建是基于 gulp + webpack 来执行的,支持开发、构建、测试等命令,详情可参阅项目模板的 README.md 文件。
官方提供了命令行工具,用于快速初始化一个项目。执行如下命令安装命令行工具:
npm install -g @wechat-miniprogram/miniprogram-cli
然后新建一个空目录作为项目根目录,在此根目录下执行:
miniprogram init --type custom-component
命令执行完毕后会发现项目根目录下生成了许多文件,这是根据官方的项目模板生成的完整项目,之后开发者可直接在此之上进行开发修改。
命令行工具的更多用法可以查看 github 仓库上的 README.md 文件。
PS:第一次使用
miniprogram init初始化项目会去 github 上拉取模板,因此需要保证网络畅通。
针对自定义组件的单元测试,可参阅文档单元测试。
以下为官方提供的自定义组件,可以参考并使用:
以下为官方提供的自定义组件扩展,可以参考并使用: