如何开发微信小程序插件

582 阅读5分钟

小白以前一直都是开发微信小程序的,平时虽然使用过插件,但是开发是从来没开发过。最近,接到了一个需求,要开发插件提供给其他小程序使用,于是就慌了,赶紧查微信小程序官方文档,寻找答案。

插件,是可呗添加到小程序内直接使用得功能组件。开发者可以像开发小程序一样开发一个插件,供其他小程序使用。同时,小程序开发者可直接在小程序内使用插件,无需重复开发,为用户提供更丰富的服务。

一、首先,先要登录微信小程序后台,完成基本信息填写。

image.png

image.png

image.png

完善这些基本信息后,就可以新建插件项目了。

image.png 新建插件类型的项目后,如果创建示例项目,则项目中将包含三个目录:

  • plugin 目录:插件代码目录。
  • miniprogram 目录:放置一个小程序,用于调试插件。
  • doc 目录:用于放置插件开发文档。

miniprogram 目录内容可以当成普通小程序来编写,用于插件调试、预览和审核。下面的内容主要介绍 plugin 中的插件代码及 doc 中的插件开发文档。

我们提供了 一个可以直接在微信开发者工具中查看的完整插件示例,开发者可以和本文互相对照以便理解。请注意:

  1. 由于插件需要 appid 才能工作,请填入一个 appid;
  2. 由于当前代码片段的限制,打开该示例后请 手动将 appid 填写到 miniprogram/app.json 中(如下图)使示例正常运行。

手动填写 appid

插件目录结构

一个插件可以包含若干个自定义组件、页面,和一组 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 段中列出(参考上文)。

除去接口限制以外,自定义组件的编写和组织方式与一般的自定义组件相同,每个自定义组件由 wxmlwxssjs 和 json 四个文件组成。具体可以参考 自定义组件的文档

页面

插件从小程序基础库版本 2.1.0 开始支持页面。插件可以定义若干个插件页面,可以从本插件的自定义组件、其他页面中跳转,或从使用者小程序中跳转。所有页面必须在配置文件的 pages 段中列出(参考上文)。

除去接口限制以外,插件的页面编写和组织方式与一般的页面相同,每个页面由 wxmlwxssjs 和 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!')
  }
}

插件如何引用小程序提供的一些方法

在小程序index.js文件可以导出一些方法,提供给插件使用(第三方小程序需要沟通支持)

// index.js
const webviewPath = 'SINAN-WEBVIEW-PATH'

/**
 * DEFN 空方法
 * @returns {undefined} 无返回值
 */
const DEFN = () => {};

class TMS {
    constructor() {
        this.wxc = wx
        this.component = false // 是否为组件方式
        this.navPageMap = new Map() // 页面跳转设置

    }

    bind(wxc) {
        this.wxc = wxc || wx

        return this
    }

    /**
  * scope 方法
  * @param {boolean} fpsc 是否强制使用插件页面wx作用域
  * @returns {object} 当前wx 调用域
  */
    scope(fpsc) {
        return this.component && !fpsc ? wx : this.wxc
    }

    // 跳转其他页面
    navigateToPlugin(setting) {
        const {
            url,
            appId,
            moduleName,
            fpsc,
            events,
            success,
            fail,
            complete
        } = setting

        const page = this.navPageMap.get(moduleName || appId)
		
        let param = {}

        if (!!fpsc) {
            param.url = `${page}${/\?/.test(page) ? '&' : '?'}name=${moduleName || appId}&path=${encodeURIComponent(url)}`
        } else {
          param.url = `plugin://${moduleName || appId}${url}`
        }

        if (events) {
            param.events = events
        }

        if (success) {
            param.success = success
        }

        if (fail) {
            param.fail = fail
        } else {
          param.fail = err => {
            console.error(err)
            console.log(param.url)
          }
        }

        if (complete) {
            param.complete = complete
        }

		  this.scope(fpsc).navigateTo(param)
    }
	
	
  /**
  * navigateToWebview 方法 从插件中跳转到小程序的 web-view 容器打开 H5
  * @param {object} setting 配置信息
  * @param {boolean} setting.fpsc 是否强制使用插件页面wx作用域
  * @param {string} setting.url 需要跳转的 H5 连接
  * @param {function} setting.complete 跳转成功后的回调函数
  * @param {function} setting.message 用于获取 H5 中的 postMessage 的数据
  * @returns {undefined} 无返回值
  */
   navigateToWebview({ fpsc, url: webUrl, complete = DEFN, message: cb }) {
    const url = encodeURIComponent(webUrl);
    const routerPath = this.navPageMap.get(webviewPath);
    this.scope(fpsc).navigateTo({
      url: `${routerPath}?url=${url}`,
      complete,
      events: {
        onMessage: (res) => {
          typeof cb === 'function' && cb(res);
        },
      },
    });
  }
}

let tms = new TMS

tms.navPageMap.set(webviewPath, '/pages/webview/webview')
// tms.navPageMap.set('wx381a393cd6daf202', '/pages/webview/redirect')

module.exports = {
    TMSBridge: tms
}

获取小程序导出

在开发者工具中预览效果,需要手动填写一下 miniprogram/app.json 中的插件 AppID

从基础库 2.11.1 起,在插件中有全局函数 requireMiniProgram,可以获取由使用者小程序导出的内容。

那么在插件中,可以这样获得内容:

// 插件
const miniProgramExports = requireMiniProgram();
miniProgramExports.navigateToWebview({ fpsc, url: webUrl, complete = DEFN, message: cb); // 'Greetings from Weixin MiniProgram!'

另外也可以 参考使用者小程序的相关文档