[toc]
小程序插件的本质是以小程序自定义组件(component)为载体,通过微信公众平台的审核机制发布,提供给第三方小程序调用功能的一种封装形式。
插件既可以只含js文件(提供API接口,配置,通用函数,SDK等), 也可以是一个或多个组件(提供模板、样式及数据集合等)。
需要注意的是:插件中的组件除了需遵循插件的目录结构、构造方法和生命周期外,只能通过配置文件显示声明外部可被调用的方法。原因是出于插件保护策略,运行时的小程序容器无法获取插件内的组件实例对象(参考文档)。
上传的小程序中,分为运行事例和插件源码两部分,其中放在「miniprogram」文件夹中的程序,只做开发和调试使用。真正上传的并分发给授权小程序的代码,是经过打包压缩后的「plugin」文件夹里的代码,这部分公司是由微信开放平台完成的,其中「api」用于存放外部接口,「components」用于放置组件。
小程序接口可以利用插件作用域存储数据,也可以请求服务端接口。需要特别说明的是,调用服务端的接口域名需要加白。
接口开发代码示例 plugin/api/data.js
/**
* 引用相对路径的模块,此处用于解决外网域名问题
* 如: api.sit.ffan.com
* @type {fixDomain}
*/
const fixDomain = require('./domain').fixDomain
/**
* 利用模块域存放本地数据,例如某些初始化配置,样式主题等
* @type {{message}}
*/
let data = {
'message': data,
}
/**
* 设置插件作用域的数据
* @param value
*/
function setData(value) {
data = value
}
/**
* 请求服务端接口,此demo模拟请求广场数据
* 需要特别注意的是,服务端接口在授权小程序中,需添加至插件白名单
* @param ids
* @return {Promise<Response>}
*/
const getPlazaIds = ids => fetch(
fixDomain(`/plazas/${ids}`, __ENV__), {
method: 'get'
}
)
/**
* 通过 CommonJS modules 规范暴露接口
* @type {{getPlazaIds: function(*): Promise<Response>, setData: setData}}
*/
module.exports = {
getPlazaIds,
setData,
}
使用 requirePlugin
方法获取插件的实例
const plazaAPI = requirePlugin('wanda-plaza')
plazaAPI.getPlazaIds()
被外部调用的组件需要在 plugin/plugin.json
中声明引用,通过键值对的方式暴露给授权小程序。代码如下:
plugin/plugin.json
{
/* publicComponents 暴露插件的组件引用 */
"publicComponents": {
"list": "components/list/list",
"plazaList": "components/plazaList/plazaList"
},
/* main值决定插件接口的入口文件 */
"main": "index.js"
}
小程序内的插件组件由 json wxml wxss js 4个文件组成,与自定义组件不同的地方是,插件由于内部保护机制,部分接口不可调用,具体可参考插件调用 API 的限制
plugin/components/list/list.js
Component({
/**
* 插件内组件的私有数据,在视图内属于单项绑定关系
*/
data: {
list: []
},
methods: {
/**
* 公有方法,可被外部组件调用
* @param product
*/
send: (product) => {
this._mockSendData(product.price, 1000)
},
/**
* 私有方法,建议以下划线开头
* @param data
* @param delay
* @return {Promise<any>}
* @private
*/
_mockSendData: (data, delay) => new Promise((resolve, reject) => {
setTimeout(function () {
resolve(data)
}, delay)
}),
/**
* 该方法可被 wxml 模板中的结构进行绑定
* @param e
*/
buy: function (e) {
const current = this.data.list.find(
item => String(item.id) === e.target.id)
if (!current) {
console.log('--Not found--')
return
}
wx.showLoading({
title: '请稍候',
mask: true,
})
this.send(current).then(value => {
wx.showToast({
title: `成功支付${value}元`
})
})
}
},
/**
* 生命周期函数,在组件加载时被调用
*/
attached: function () {
this.setData({
list: [{
id: 101,
name: '水费',
price: 1
}, {
id: 102,
name: '电费',
price: 2
}, {
id: 103,
name: '燃气费',
price: 3
}]
})
},
})
plugin/components/list/list.wxml
<view class="product-header">
生活缴费
</view>
<view wx:for="{{list}}" wx:key="id" class="product-list">
<view class="product-item">
<text class="product-text">{{item.name}}</text>
<text class="product-price">{{item.price}}元</text>
<button size="mini" id="{{item.id}}" class="product-btn-buy" bindtap="buy">购买</button>
</view>
</view>
plugin/components/list/list.wxss
.product-header {
font-size: 20px;
margin: 20px 0;
padding: 0 20px;
border-bottom: 1px solid #ccc;
}
.product-item {
display: flex;
padding: 0 20px;
color: #666666;
justify-content: space-between;
align-items: center;
height: 120rpx;
border-bottom: 1px solid #cccccc;
}
.product-text {
flex: 2 1 auto;
}
.product-price {
color: orangered;
font-size: 14px;
width: 150rpx;
flex: 0 1 auto;
}
.product-btn-buy {
flex: 0 1 auto;
}
最后,插件内部是需要基础设置:
project.config.json
{
"miniprogramRoot": "./miniprogram",
"pluginRoot": "./plugin",
"compileType": "plugin",
"setting": {
"newFeature": true
},
"appid": "wxb7cce62bced42205",
"projectname": "square_plugins",
"condition": {}
}
当上述工作完成后,通过与小程序一致的入口上传程序,即可走审核流程了
在插件通过审核后,第三方插件通过选择「设置」-「第三方服务」-「插件管理」中选择「添加插件」,输入插件 AppID,提出插件使用申请。
开发者可以在小程序插件审核插件使用申请,可以通过、拒绝申请。
授权的第三方小程序(比如周浦广场)项目根目录下的 app.json
声明调用的插件:
miniprogram/app.json
{
"pages": [
"pages/index/index"
],
"plugins": {
/**
* 此处是插件对外暴露的key
* 一个第三方小程序可以引用多个小程序插件
*/
"chargePlugin": {
"version": "dev",
/* 调用小程序的值是 project.config.json 的appid */
"provider": "wxb7cce62bced42205"
}
}
}
这样即可在程序内调用小程序插件了!
提交插件遇到「类目不一致」的问题,目前只有一部分类目开放小程序插件申请功能。
咱们测试广场的小程序「线下超市」就不能开发小程序:
当前允许开发的小程序类目如下:
因为「插件名称」目前不开放修改,所以申请开发插件前请慎重!再慎重! 测试帐号就因为申请名称为「广场」。审核通过的前提条件是:插件名称,插件内容,插件类目 三者完全匹配。