基于 Taro 3 开发微信小程序插件:build-weapp-plugin 实战指南
2026/9/19 20:21:03 网站建设 项目流程

基于 Taro 3 开发微信小程序插件:build-weapp-plugin 实战指南

【免费下载链接】taro开放式跨端跨框架解决方案,支持使用 React/Vue 等框架来开发微信/京东/百度/支付宝/字节跳动/ QQ 小程序/H5/React Native 等应用。项目地址: https://gitcode.com/gh_mirrors/tar/taro

微信小程序插件支持将组件、页面和接口封装成独立单元,供其他小程序直接引用,大幅提升跨项目复用效率。本指南以 Taro 仓库中的 build-weapp-plugin 示例工程为完整骨架,系统讲解在 Taro 3 项目中配置插件工程、开发三种插件形态(自定义组件、页面、接口)、打通插件与宿主小程序的数据流,以及如何在微信开发者工具中调试与发布,覆盖从零初始化到打包上线的全部关键步骤。

示例工程概览

build-weapp-plugin位于 Taro 仓库的 examples/build-weapp-plugin 目录,是一个使用 React 编写、基于 Webpack 5 编译的微信小程序插件 Demo。它本身既是一个可独立编译的 Taro 工程,又是一个标准的微信小程序插件项目,因此同时包含两类文件:

  • 宿主侧源码:位于src/,其中src/app.config.ts声明如何引用插件,src/pages/index/index.tsx是用于验证插件能力的测试页面;
  • 插件侧源码:位于src/plugin/,内含plugin.json(插件配置清单)、index.ts(插件接口实现)、components/avatar(插件组件)、pages/list(插件页面)。

工程通过miniprogramRootpluginRoot将编译产物划分为两个相互独立的目录(详见下文"工程配置"一节),既保证插件目录不被宿主逻辑污染,也便于微信开发者工具按插件类型识别。

工程的依赖以 Taro 3.6 系为核心(@tarojs/taro@tarojs/react@tarojs/runtime@tarojs/components@tarojs/plugin-framework-react等均为3.6.24),框架选用 React 18,样式方案为 Sass,完整依赖清单见 package.json。

快速开始:四步跑通示例

1. 配置 appid

插件与宿主小程序必须绑定同一 AppID,否则开发者工具无法完成插件的注册与加载。按 README 要求修改两处:

  1. project.config.json 中的appid字段(示例中为wxa9abf43f10a7bdb0);
  2. src/app.config.ts 中plugins.myPlugin.provider字段,同样填该 AppID。

若跳过此步,微信开发者工具会使用默认的测试 appid,插件将无法关联到宿主账号下进行真机调试与上传。

2. 安装依赖并编译

examples/build-weapp-plugin目录下依次执行:

# 安装依赖 $ yarn # 开发模式(监听文件变更,实时重新编译) $ npm run dev # 生产模式(产物压缩、体积优化) $ npm run build

两个脚本在 package.json 中定义:

{ "scripts": { "dev": "taro build --plugin weapp --watch", "build": "taro build --plugin weapp" } }

--plugin weapp是 Taro CLI 面向微信小程序插件的专用编译模式;--watch开启监听,开发时保存源码会自动增量编译,产物输出到miniprogram/目录。

3. 开发位置约定

插件逻辑全部位于src/plugin内,包括组件、页面与接口;而src/pages/index则是用于测试插件的宿主页面,它负责以"使用者"的视角调用插件,验证组件事件、页面跳转与接口调用是否正常。二者隔离存放,职责清晰。

4. 导入开发者工具预览

使用微信开发者工具导入项目时,项目路径必须指向build-weapp-plugin/miniprogram(即编译产物目录,而非仓库根目录或src)。导入后开发者工具根据project.config.json中的miniprogramRootpluginRoot自动区分宿主代码与插件代码。

工程配置详解

project.config.json:插件类型项目声明

{ "miniprogramRoot": "miniprogram/", "pluginRoot": "plugin/", "compileType": "plugin", "appid": "wxa9abf43f10a7bdb0", "projectname": "build-weapp-plugin" }

关键字段说明:

  • compileType: "plugin":向开发者工具声明这是一个插件项目,而非普通小程序;
  • miniprogramRoot:宿主测试小程序(编译产物)的根目录;
  • pluginRoot:插件(编译产物)的根目录,二者缺一不可;
  • appid:插件所属小程序的 AppID,必须与src/app.config.ts中的provider一致。

config/index.js:Taro 构建配置

Taro 侧的构建配置位于 config/index.js,其中两个配置项与插件构建强相关:

  • outputRoot: 'miniprogram':把 Taro 编译产物输出到miniprogram/,与project.config.jsonminiprogramRoot对应;
  • copy.patterns:把宿主测试页引用插件时所需的额外文件复制进产物目录:
copy: { patterns: [ { from: 'src/my-export.js', to: 'miniprogram/miniprogram/my-export.js' } ] }

该 copy 配置服务于插件export机制(详见"插件接口"一节):由于宿主侧通过export: 'my-export.js'引用该文件,而插件与宿主是两套独立构建产物,因此必须显式把src/my-export.js复制到宿主产物的miniprogram/miniprogram/下,保证运行时能按相对路径找到。

其余配置(designWidth: 750deviceRatioframework: 'react'compiler.type: 'webpack5'mini.postcss中的pxtransform/url等)与普通 Taro 工程一致,此处不再展开。

三种插件形态的开发

示例通过 src/plugin/plugin.json 同时声明了三种插件能力:

{ "publicComponents": { "avatar": "components/avatar/avatar" }, "pages": { "list": "pages/list/list" }, "main": "index.ts" }
  • publicComponents:对外暴露的插件组件,键为宿主侧使用的组件名,值为组件路径;
  • pages:对外暴露的插件页面,宿主可跳转;
  • main:插件接口入口,宿主通过Taro.requirePlugin调用。

插件组件:props 与事件传递

插件组件 Avatar 位于 src/plugin/components/avatar/avatar.tsx,核心代码如下:

export default class Avatar extends Component<{ mode: any, onAvatarClick: any }, null> { node: { ctx: any } handleClick () { if (process.env.TARO_ENV === 'jd') { this.node.ctx.triggerEvent('avatarClick') } else { this.node.ctx.triggerEvent('avatar-click') } } render () { return ( <View ref={node => this.node = node} > <Text>triggerEvent 触发点击事件:</Text> <Image className='logo' src='http://storage.360buyimg.com/taro-static/static/images/logo.png' mode={this.props.mode} onClick={this.handleClick.bind(this)} /> <Text>props 传递点击事件:</Text> <Image className='logo' src='http://storage.360buyimg.com/taro-static/static/images/logo.png' mode={this.props.mode} onClick={this.props.onAvatarClick} /> </View> ) } }

该组件演示了插件组件的两条核心数据通道(即 README 中提到的"插件组件测试特性"):

  1. props 传递:宿主把mode等属性直接传给插件组件,组件在渲染层消费;
  2. 事件传递与触发
    • 事件入参:宿主通过onAvatarClick回调把事件传入组件,组件直接在onClick中调用;
    • 事件出参:组件内通过this.node.ctx.triggerEvent('avatar-click')触发事件上抛给宿主。注意 Taro 用ref拿到自定义组件实例,再读取其内部ctx(Component 实例)调用triggerEvent,且京东端事件名需用驼峰avatarClick,微信端用短横线avatar-click,这是跨端命名差异的典型处理。

在宿主测试页 src/pages/index/index.tsx 中,两种方式同时被验证:

<avatar onAvatarClick={() => console.log('组件事件传递成功')} props={{ mode: 'aspectFit', onAvatarClick: () => console.log('组件事件传递成功') }} />

可见宿主既把onAvatarClick作为 props 直接传入,又把它包裹在props对象中一并传递,覆盖两种用法。

插件页面:选择器、分享与泛型组件

插件页面list位于 src/plugin/pages/list/list.tsx,对应 README 中的"插件页面测试特性",逐一验证了以下能力:

1. 获取小程序渲染层元素

getElement = () => { const query = Taro.createSelectorQuery().in(this.props.$scope) query.select('.page').boundingClientRect().exec(res => { console.log(res) }) }

通过Taro.createSelectorQuery()创建查询,并用.in(this.props.$scope)把查询作用域限定到插件页面自身,再.select('.page').boundingClientRect()获取元素布局信息。这是插件页面操作渲染层节点的标准姿势。

2. 分享生命周期

onShareAppMessage() { return { title: '测试分享', path: '/pages/index/index' } }

插件页面同样可以定义onShareAppMessage分享生命周期钩子,返回分享标题与路径。

3.genericsImplementation泛型组件

插件页面声明了泛型组件,见 src/plugin/pages/list/list.config.ts:

export default { "componentGenerics": { "mp-comp": true } }

并在页面中使用占位:

<mp-comp></mp-comp>

泛型组件的实际实现由宿主侧通过app.config.ts中的genericsImplementation指定:

genericsImplementation: { list: { 'mp-comp': 'component/comp' } }

即:在名为list的插件页面里,把泛型占位mp-comp替换为宿主自己的组件component/comp。这样插件页面可以"留白"给宿主填充组件,实现页面骨架复用、外观定制的效果。

注意宿主测试页 src/pages/index/index.tsx 中同样渲染了一个<mp-comp></mp-comp>,注释说明这是 hack:为了让genericsImplementation生效——因为当前构建链路还没有收集插件中使用到的第三方组件,需要在宿主侧手动保留一个占位以触发泛型解析。

插件页面中的ListItem组件(src/plugin/components/listItem/listItem.tsx)是一个纯展示组件,接收namevalue两个 props 渲染列表项,用于验证插件页面内部使用自有组件的能力。

插件接口:main 入口与 export 参数

1. main 入口(Taro.requirePlugin

插件接口实现在 src/plugin/index.ts:

export function sayHello () { console.log('Hello plugin!') } export const answer = 42

宿主侧通过Taro.requirePlugin('myPlugin')拿到整个插件接口对象并调用:

usePluginInterface () { const myPluginInterface = Taro.requirePlugin('myPlugin') myPluginInterface.sayHello() const answer = myPluginInterface.answer console.log('answer: ', answer) }

Taro.requirePlugin是微信小程序requirePluginAPI 在 Taro 中的封装,参数myPlugin与宿主app.config.tsplugins字段声明的键名一致。

2. 宿主页面通过 export 暴露参数给插件(README 中"其它测试")

插件页面listcomponentDidMount中通过requireMiniProgram()反向读取宿主暴露的数据:

declare const requireMiniProgram: () => { whoami: string } componentDidMount () { // 测试 export 京东小程序不支持在插件侧调用 if (process.env.TARO_ENV !== 'jd') { console.log(requireMiniProgram().whoami) } }

宿主侧配套做了三件事:

  • 定义暴露文件 src/my-export.js:module.exports = { whoami: 'Wechat MiniProgram' }
  • 在 src/app.config.ts 的插件声明中加入export: 'my-export.js'
  • 在 config/index.js 中通过copy.patterns把该文件复制到miniprogram/miniprogram/my-export.js,确保插件运行时能按相对路径加载。

这一闭环演示了"宿主向插件传递参数"的机制:插件侧拿到的是宿主小程序的导出模块,可据此读取宿主上下文信息。同时代码注释标明京东小程序暂不支持在插件侧调用该能力,是跨端兼容性的重要提示。

宿主测试页完整结构

宿主测试页 src/pages/index/index.tsx 汇总了上述全部能力的使用方式:

import Taro from '@tarojs/taro' import React, { Component } from 'react' import { View, Button, Navigator } from '@tarojs/components' export default class Index extends Component { usePluginInterface () { /* 见上文 */ } render () { return ( <View className='index'> {/** 测试插件组件 */} <avatar onAvatarClick={...} props={{...}} /> {/** 测试插件页面 */} <Navigator url='plugin://myPlugin/list'> <Button>跳转到插件页面</Button> </Navigator> {/** 使用插件接口 */} <Button onClick={this.usePluginInterface}>测试插件接口</Button> {/** hack:为了让 genericsImplementation 生效 */} <mp-comp></mp-comp> </View> ) } }

几点关键用法:

  • 插件页面跳转plugin://协议是微信小程序跳转插件页面的专用 scheme,格式为plugin://插件名/页面路径,这里对应plugin.jsonpages.list的值pages/list/list
  • 宿主通过Navigator组件或Taro.navigateTo均可发起跳转;
  • 宿主自身的页面声明在 src/app.config.ts 的pages数组,插件声明在其plugins字段:
plugins: { myPlugin: { version: 'dev', provider: 'wxa9abf43f10a7bdb0', genericsImplementation: { ... }, export: 'my-export.js' } }

其中version: 'dev'表示使用开发者工具中的"开发版"插件进行联调;实际发布时需替换为正式版本号。

插件文档编写约定

src/plugin/doc目录用于存放插件文档,README.md 给出了书写约定:

  • 插件文档支持 Markdown 的多级标题;
  • 引用图片时必须以相对路径引用doc目录下的本地图片(如[![链接](https://link.gitcode.com/i/f67c2ca26f6b355f6cb58530cbbb83b3)](https://link.gitcode.com/i/f7e876ba49f22972bae62522118e590c)),不能使用网络图片或doc目录之外的图片;
  • 使用微信开发者工具编辑器的上传按钮可上传插件文档,上传内容包括doc目录下的README.md与图片。

该文档与示例中的 example.jpeg 一同构成插件详情页展示素材,属于微信插件发布流程的一部分。

从示例走向生产

build-weapp-plugin覆盖了微信小程序插件开发的完整链路,可作为生产项目的起点模板:

  1. 复用骨架:把src/plugin下的plugin.json、组件、页面、接口入口整体迁移到业务工程,替换appidprovider
  2. 扩展能力:按需在publicComponentspages中追加新的插件组件与页面;需要宿主定制外观时使用componentGenerics+genericsImplementation组合;
  3. 构建产物dev/build脚本产物在miniprogram/,其中plugin/为插件本体、miniprogram/为测试宿主,导入开发者工具时路径指向build-weapp-plugin/miniprogram
  4. 发布前检查:确认project.config.jsoncompileType: "plugin"与 appid 无误、export文件已通过copy.patterns正确复制、插件文档图片均为doc目录内的相对路径引用;
  5. 跨端注意:事件命名(avatarClick/avatar-click)与requireMiniProgram可用性均存在京东端差异,涉及京东小程序适配时需按process.env.TARO_ENV === 'jd'分别处理。

至此,你已经掌握在 Taro 3 中开发微信小程序插件组件、插件页面与插件接口的完整方法,并理解了triggerEvent事件上抛、Taro.requirePlugin接口调用、genericsImplementation泛型替换与export参数回传四条关键数据通道的底层配合方式。

【免费下载链接】taro开放式跨端跨框架解决方案,支持使用 React/Vue 等框架来开发微信/京东/百度/支付宝/字节跳动/ QQ 小程序/H5/React Native 等应用。项目地址: https://gitcode.com/gh_mirrors/tar/taro

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询