Uniapp开发微信小程序插件的一些心得
一、uniapp 开发微信小程序框架搭建
1. 通过 vue-cli 创建 uni-ap
// nodejs使用18以上的版本
nvm use 18.14.1
// 安装vue-cli
npm install -g @vue/cli@4
// 选择默认模版
vue create -p dcloudio/uni-preset-vue plugindemo
// 运行 uniapp2wxpack-cli
npx uniapp2wxpack --create
2. 手动在项目根目录创建插件开发需要的 project.config.json
并且内容 miniprogramRoot 和 pluginRoot 属性按以下填写,并且在 appid 字段中自行填写真实的 appid(小程序的 appid)
// project.config.json
{"miniprogramRoot": "miniprogram/","pluginRoot": "uniSubpackage/","compileType": "plugin","setting": {},"appid": "xxxxxxxxx","projectname": "plugindemo","simulatorType": "wechat","simulatorPluginLibVersion": {},"condition": {}
}
3. 在 src 目录下手动创建 plugin.json,
main 属性必须按以下内容填写,也就意味着插件的接口文件指向 src/main.js(因为打包后路径会变成 common/main.js)
{"publicComponents": {"hello-component": "components/test"},"pages": {"yuwen-page": "pages/textbook/index"},"main": "common/main.js"
}
4. 运行命令编译
npm run dev:mp-weixin-pack-plugin (开发模式)
npm run build:mp-weixin-pack-plugin (生产模式)
此部分详细内容可参考uniapp + uniapp2wxpack
5 生成的完整目录如下



6 打包生成的目录

7 增加插件文档支持
- 在项目根目录增加doc文件夹,新建README.md文件,作为插件的文档
- 项目打包后,手动将doc文件夹拷贝到 dist/dev/mp-weixin-pack-plugin目录
- 微信开发者工具单击右键doc文件夹,上传插件文档
- 在微信公众平台,插件基本信息,更新插件文档
二、uniapp 开发微信小程序插件遇到的问题及解决
1 当前 uniapp 开发插件,插件内部跳转报错 `navigateTo:fail rejected due to no permission currently`
经过定位问题,发现属于uniapp的框架问题,uniapp封装了wx.和uni., 导致uni.navigateTo、uni.request 的权限都是主小程序的,而不是插件内的,在编译生成的代码里把对应的硬改成 wx. 的方法,程序不回报错,但是这样是治标不治本,只能说定位到问题出现在这块儿。
解决办法:
- 将`wx.js` 替换 `/node_modules/@dcloudio/uni-mp-weixin/dist/wx.js`
- 将`index.js ` 替换 `/node_modules/@dcloudio/vue-cli-plugin-uni/lib/mp/index.js`
- index.js下载地址 和 wx.js下载地址
- uniapp官方原贴
2 插件总线通信问题
按照微信官方文档,在plugin.json可以设置main,提供一个index.js给到小程序调用(通过requirePlugin()方法获得),然后本帖的框架main.js是项目的入口程序,不能通过module.export导出。
解决方案:
uniapp预置了一个__uniPluginExports接口,可以在上面写index.js需要暴露的方法和功能。
// src/main.js
...
const app = new Vue({
...
})// 用来给引用的小程序使用的,相当于原生小程序插件写法的index.js
__uniPluginExports = {eventBus: {},...,其他方法
}
三、插件-小程序通过事件总线通信
1 插件可以预置一个eventBus事件总线,供插件和小程序通信使用。
对应__uniPluginExports的eventBus,小程序通过requirePlugin()获取并使用。
// 用 JS 实现简易版的事件总线
class EventBus {constructor () {this._events = new Map()}// next 触发某个行为next (type, ...args) {let handler = this._events.get(type)if (Array.isArray(handler)) {// 如果 handler 是数组,说明有多个监听者,需要依次触发里边的函数for (let i = 0; i < handler.length; ++i) {if(handler[i]){if (args.length > 0) {handler[i].apply(this, args)} else {handler[i].call(this)}}}} else {if (handler) {// 单个函数的情况直接触发即可if (args.length > 0) {handler.apply(this, args)} else {handler.call(this)}}}return true}// subscribe 订阅/监听某个行为subscribe (type, fn) {const handler = this._events.get(type) // 获取对应事件名称的函数清单if (!handler) {this._events.set(type, fn)} else if (handler && typeof handler === 'function') {// 如果 handler 是函数,说明当前只有一个监听者// 再次添加监听者,需要改用数组储存this._events.set(type, [handler, fn])} else {// 已有多个监听者,直接往数组里 push 函数即可handler.push(fn)}}// destroy 销毁事件destroy (type, fn) {const handler = this._events.get(type) // 获取对应事件名称的函数清单// 如果是函数,说明只有一个监听者,直接删除if (handler && typeof handler === 'function') {this._events.delete(type)} else {handler.splice(handler.findIndex(e => e === fn),1)}}
}export const eventBus = new EventBus()
2 插件可以通过requireMiniProgram()获取小程序app.json暴露出的index.js,
并可以根据配置来初始化插件的一些信息。
// 宿主小程序的app.json
{"pages": [],"plugins": {"plugin":{"version": "","provider": "插件appId","export": "index.js","genericsImplementation": {"plugin-page": {"mp-view": "这里是宿主小程序自定义组件的路径"}}}}
}
// 宿主小程序index.js, 暴露给插件的一些配置项
module.exports = {....
}
// 插件获取小程序暴露的index.js
const miniProgramExports = requireMiniProgram(); // 接收小程序通过index.js传过来的数据
3 通过事件总线实现小程序插件通信
插件给小程序发消息
import { eventBus} from '@/utils/eventBus';eventBus.next('方法名', {
... // 传参
});// 在页面|组件销毁前,记得执行destory()方法注销事件订阅
eventBus.destory('方法名')
小程序订阅插件消息
const plugin = requirePlugin('插件名');
plugin.eventBus.subscribe('事件名', () => {
// 回调函数
})
4 引用小程序的自定义组件
插件开发官方原贴
4.1 page.json 配置componentGenerics
// 插件目录 src/pages.json
{"pages": ["path": "pages/index/index","style": {"navigationBarTextStyle": "black","navigationBarBackgroundColor": "#FFFFFF","backgroundColor": "#F8F8F8","navigationBarTitleText": "课本朗读",// 配置componentGenerics"componentGenerics": {"mp-view": true}}]
}
4.2 plugin.json配置页面标签
// 插件 src/plugin.json
{// 配置公共组件"publicComponents": {},"pages": {"plugin-page": "pages/index/index"},"main": "common/main.js"
}
4.3 插件pages/index/index.vue页面使用mp-view
<template><view>...<mp-view></mp-view></view>
</template><script>
...
</script><style lang="scss" scoped>
...
</style>
4.4 宿主小程序app.json配置genericsImplementation, 声明自定义组件
// 宿主小程序的app.json
{"pages": [],"plugins": {"plugin":{"version": "","provider": "插件appId","export": "index.js","genericsImplementation": {"plugin-page": {"mp-view": "这里是宿主小程序自定义组件的路径"}}}}
}
四、插件预置方法
1 微信不支持宿主小程序直接从插件页面跳转宿主小程序的页面。所以可以通过插件预置的方法实现
// 插件src/main.jsimport { eventBus } from '@/utils/eventBus ';...// 用来给引用的小程序使用的
__uniPluginExports = {eventBus: eventBus,/*** 在插件内跳转到小程序页面* @param url{string} 页面 URL* @returns {Promise<unknown>}*/jumpPage: function (url) {return new Promise((resolve, reject) => {uni.navigateTo({url: url,success(e) {resolve(e);},fail(e) {reject(e);},});});},jumpPageBack() {uni.navigateBack({fail(e) {console.log('uni.navigateBack', e);},});},/*** 在插件内跳转到小程序页面,并关闭当前页面* @param url{string} 页面 URL* @returns {Promise<unknown>}*/jumpPageRedirect: function (url) {return new Promise((resolve, reject) => {uni.redirectTo({url: url,success(e) {resolve(e);},fail(e) {reject(e);},});});},/*** 在插件内跳转到小程序页面* @param url{string} 页面 URL* @returns {Promise<unknown>}*/reLaunch(url) {return new Promise((resolve, reject) => {uni.reLaunch({url: url,success(e) {resolve(e);},fail(e) {reject(e);},});});}
}
宿主小程序调用插件跳转路由方法
const plugin = requirePlugin('插件名');
plugin.jumpPage('这里传入小程序的url')
2 某些场景,插件需要跳转h5页面,微信小程序插件不支持webview,所以需要使用宿主小程序跳转webview页面
具体步骤如下:
- 插件通过事件总线触发一个自定义的webview事件通知宿主小程序,并传入h5的url
- 宿主小程序订阅webview的事件,得到h5的url地址
- 宿主小程序调用插件暴露出的jumpPage方法,跳转自身webview页面,并保存h5地址
- 宿主小程序在webview页面拿到h5地址并渲染页面
相关文章:

Uniapp开发微信小程序插件的一些心得
一、uniapp 开发微信小程序框架搭建 1. 通过 vue-cli 创建 uni-ap // nodejs使用18以上的版本 nvm use 18.14.1 // 安装vue-cli npm install -g vue/cli4 // 选择默认模版 vue create -p dcloudio/uni-preset-vue plugindemo // 运行 uniapp2wxpack-cli npx uniapp2wxpack --…...

Vscode通过Roo Cline接入Deepseek
文章目录 背景第一步、安装插件第二步、申请API key第三步、Vscode中配置第四步、Deepseek对话 背景 在前期介绍【IDEA通过Contince接入Deepseek】步骤和流程,那如何在vscode编译器中使用deepseek,记录下来,方便备查。 第一步、安装插件 在…...

不同规模企业如何精准选择AI工具: DeepSeek、Grok 和 ChatGPT 三款主流 AI 工具深度剖析与对比
本文深入探讨了最近国内外主流的 DeepSeek、Grok 和 ChatGPT 三款主流 AI 工具的技术细节、性能表现、应用场景及局限性,并从技术能力、功能需求、成本预算、数据安全和合规以及服务与支持五个关键维度,详细分析了不同规模企业在选择 AI 工具时的考量因素…...

如何有效判断与排查Java GC问题
目录 一、GC的重要性与对性能的影响 (一)GC对性能的影响简要分析 1.GC暂停与应用停顿 2.GC吞吐量与资源利用率 3.GC对内存管理的作用:资源回收 4.GC策略与优化的选择 (二)GC的双刃剑 二、GC性能评价标准 &…...

【笔记】用大预言模型构建专家系统
最近闲庭漫步,赏一赏各个AI大语言模型芳容。也趁着时间,把倪海夏一家的天纪和人纪视频看完了,感谢倪先生和现在网络的知识分享,受益匪浅。但是发现看完,很多不错的知识都不能记录在脑子里,那用的时候岂不是…...
Android SystemUI深度定制实战:下拉状态栏集成响铃功能开关全解析
一、功能实现全景视图 目标场景:在Android 14系统级ROM定制中,为SystemUI下拉状态栏的QuickQSPanel区域新增响铃模式切换开关,实现静音/响铃快速切换功能。该功能需通过三层关键改造实现: 二、核心实现三部曲 1. 配置注入&…...

【Python】基础语法三
> 作者:დ旧言~ > 座右铭:松树千年终是朽,槿花一日自为荣。 > 目标:了解Python的函数、列表和数组。 > 毒鸡汤:有些事情,总是不明白,所以我不会坚持。早安! > 专栏选自ÿ…...

[Computer Vision]实验六:视差估计
目录 一、实验内容 二、实验过程 2.1.1 test.py文件 2.1.2 test.py文件结果与分析 2.2.1 文件代码 2.2.2 结果与分析 一、实验内容 给定左右相机图片,估算图片的视差/深度;体现极线校正(例如打印前后极线对)、同名点匹配…...

【 开发知识点 一 】 随机数生成器 /dev/urandom 和 /dev/random
文章目录 一、随机数生成器 是什么 ?二、为什么 需要 随机数生成器 ?三、随机数生成器 基本原理四、随机数生成器 三个输出接口五、随机生成器 应用1、简单应用2、项目应用一、随机数生成器 是什么 ? /dev/random 和 /dev/urandom 是 Linux 上的字符设备文件,它们是随机数…...

LabVIEW虚拟弗兰克赫兹实验仪
随着信息技术的飞速发展,虚拟仿真技术已经成为教学和研究中不可或缺的工具。开发了一种基于LabVIEW平台开发的虚拟弗兰克赫兹实验仪,该系统不仅能模拟实验操作,还能实时绘制数据图形,极大地丰富了物理实验的教学内容和方式。 …...

LLC谐振变换器恒压恒流双竞争闭环simulink仿真
1.模型简介 本仿真模型基于MATLAB/Simulink(版本MATLAB 2017Ra)软件。建议采用matlab2017 Ra及以上版本打开。(若需要其他版本可联系代为转换)针对全桥LLC拓扑,利用Matlab软件搭建模型,分别对轻载…...

TVbox蜂蜜影视:智能电视观影新选择,简洁界面与强大功能兼具
蜂蜜影视是一款基于猫影视开源项目 CatVodTVJarLoader 开发的智能电视软件,专为追求简洁与高效观影体验的用户设计。该软件从零开始编写,界面清爽,操作流畅,特别适合在智能电视上使用。其最大的亮点在于能够自动跳过失效的播放地址…...

Python 绘制迷宫游戏,自带最优解路线
1、需要安装pygame 2、上下左右移动,空格实现物体所在位置到终点的路线,会有虚线绘制。 import pygame import random import math# 迷宫单元格类 class Cell:def __init__(self, x, y):self.x xself.y yself.walls {top: True, right: True, botto…...

vue3学习-1(基础)
vue3学习-1(基础) 1. 开始API 风格选项式 API (Options API)组合式 API (Composition API) 快速创建个应用 2.基础1. 创建个应用2.模板语法3.响应式基础reactive() 的局限性[](https://cn.vuejs.org/guide/essentials/reactivity-fundamentals.html#limi…...

deepseek使用记录18——文化基因之文化融合
文明长河中的生命浪花 在洛阳白马寺的银杏树下,年轻母亲指着"农禅并重"碑刻给孩子讲述祖辈耕作的故事;在哔哩哔哩的直播间里,00后女孩穿着汉服跳起街舞,弹幕飘过"这才是文化缝合怪"。当文明交融的宏大叙事照…...

Hadoop简介
1. Hadoop简介 官网:http://hadoop.apache.org 1.1 Hadoop架构 Hadoop由三个模块组成:分布式存储HDFS、分布式计算MapReduce、资源调度引擎YARN 1.2 Hadoop历史 Hadoop作者Doug Cutting Apache Lucene是一个文本搜索系统库 Apache Nutch作为前者的一部…...

密码学(哈希函数)
4.1 Hash函数与数据完整性 数据完整性: 检测传输消息(加密或未加密)的修改。 密码学Hash函数: 构建某些数据的简短“指纹”;如果数据被篡改,则该指纹(以高概率)不再有效。Hash函数…...
谈谈单例模式中通过Htools包的SpringUtil.getBean获取Bean的好处
目录 优势 解决依赖注入失效问题: 典型应用场景: 好处 1. 实例化时序问题 2. 延迟获取解决空指针 3. 设计模式与 Spring 的权衡 代码对比:错误 vs 正确 错误示例(空指针): 正确实现(延…...

本地部署大语言模型-DeepSeek
DeepSeek 是国内顶尖 AI 团队「深度求索」开发的多模态大模型,具备数学推理、代码生成等深度能力,堪称"AI界的六边形战士"。 Hostease AMD 9950X/96G/3.84T NVMe/1G/5IP/RTX4090 GPU服务器提供多种计费模式。 DeepSeek-R1-32B配置 配置项 规…...

adb的安装
1、概念 (1)adb(android debug bridge)安卓调试桥,用于完成电脑和手机之间的通信控制。 (2)xcode来完成对于ios设备的操控,前提是有个mac电脑。 2、adb的安装 (1&…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...

20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...

脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...