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 --…...
0005__PyTorch 教程
PyTorch 教程 | 菜鸟教程 离线包:torch-1.13.1cpu-cp39-cp39-win_amd64.whl https://download.pytorch.org/whl/torch_stable.html...
Pikachu
一、网站搭建 同样的,先下载安装好phpstudy 然后启动Apache和Mysql 然后下载pikachu,解压到phpstudy文件夹下的www文件 然后用vscode打开pikachu中www文件夹下inc中的config.inc.php 将账户和密码改为和phpstudy中的一致(默认都是root&…...
CentOS7 使用 YUM 安装时报错:Cannot find a valid baseurl for repo: base/7/x86_64的解决方法
CentOS7 使用 YUM 安装时报错:Cannot find a valid baseurl for repo: base/7/x86_64的解决方法 报错代码解决方法 报错代码 输入命令yum update -y时报错Cannot find a valid baseurl for repo: base/7/x86_64 解决方法 有 wget 工具 更换YUM源 mv /etc/yum.…...
ChatGPT与DeepSeek:AI语言模型的巅峰对决
目录 引言 一、ChatGPT 与 DeepSeek 简介 (一)ChatGPT (二)DeepSeek 二、技术原理剖析 (一)ChatGPT 技术原理 (二)DeepSeek 技术原理 (三)技术原理对比…...
Linux----网络通信
一、IP地址详解 (一)核心概念 概念说明IP地址网络设备的唯一逻辑标识符,相当于网络世界的"门牌号"主机任何接入网络的终端设备(计算机/手机/服务器等)核心作用① 设备标识 ② 路由寻址 ③ 数据传输 &…...
Android逆向:一文掌握 Frida 详细使用
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 1. Frida 简介2. Frida 的工作原理3. 安装 Frida3.1 安装 Frida 工具3.2 安装 Frida Server4. Frida 的基本使用4.1 连接到目标设备4.2 附加到目标进程4.3 编写 Frida 脚本5. Frida 的高级用法5.1 Hook Java 方法5.2 修…...
AI军备竞赛2025:GPT-4.5的“情商革命”、文心4.5的开源突围与Trae的代码革命
AI军备竞赛2025:GPT-4.5的“情商革命”、文心4.5的开源突围与Trae的代码革命 ——一场重塑人类认知边界的技术战争 一、OpenAI的“感性觉醒”:GPT-4.5的颠覆与争议 1.1 从“冷面学霸”到“温柔导师”:AI的情商跃迁 当用户输入“朋友放鸽子&…...
5G网络切片辨析(eMBB,mMTC,uRLLC)
URLLC有三大应用场景,分别是eMBB(增强型移动宽带)、uRLLC(高可靠低延时通信)和mMTC(海量机器通信)。 增强型移动宽带(eMBB):需要关注峰值速率,容…...
【MySQL篇】数据类型
目录 前言: 1,数据类型的分类 编辑 2 ,数值类型 2.1 tinyint类型 2.2 bit类型 2.3 小数类型 2.3.1 float类型 2.3.2 decimal类型 3,字符串类型 3.1 char 3.2 varchar 3.3 char与varchar的比较 3.4日期和时间类型 3.5 …...
DockerでOracle Database 23ai FreeをセットアップしMAX_STRING_SIZEを拡張する手順
DockerでOracle Database 23c FreeをセットアップしMAX_STRING_SIZEを拡張する手順 はじめに環境準備ディレクトリ作成Dockerコンテナ起動 データベース設定変更コンテナ内でSQL*Plus起動PDB操作と文字列サイズ拡張設定検証 管理者ユーザー作成注意事項まとめ はじめに Oracle…...
Skynet入门(一)
概念 skynet 是一个为网络游戏服务器设计的轻量框架。但它本身并没有任何为网络游戏业务而特别设计的部分,所以尽可以把它用于其它领域。 设计初衷 如何充分利用它们并行运作数千个相互独立的业务。 模块设计建议 在 skynet 中,用服务 (service) 这…...
【音视频】图像基础概念
一、图像基础概念 1.1 像素 像素是一个图片的基本单位,pix使英语单词pixtureelement的结合“pixel”的简称,所以像素有图像元素之意。 例如2500*2000的照片就是指横向有2500个像素点,竖向有2000个像素点,总共500万个像素&#x…...
预训练(Pretraining)阶段为何被称为“自监督学习”(Self-Supervised Learning)?
预训练阶段为何被称为自监督学习? 在人工智能领域,尤其是自然语言处理(NLP)和深度学习的快速发展中,预训练(Pretraining)已经成为一种不可或缺的技术手段。而其中一个重要的概念是“自监督学习…...
【已解决】pyodbc 5.2 [ODBC 驱动程序管理器] 未发现数据源名称并且未指定默认驱动程序
问题 当升级 pyodbc 5.2 版本后,连接 sqlserver 数据库,报错如下: 连接失败: (IM002, [IM002] [Microsoft][ODBC 驱动程序管理器] 未发现数据源名称并且未指定默认驱动程序 (0) (SQLDriverConnect); [IM002] [Microsoft][ODBC 驱动程序管理…...
时钟树的理解
对应电脑的主板,CPU,硬盘,内存条,外设进行学习 AHB总线 -72MHZ max APB1总线 -36MHZ max APB2-72MHZ max 时序逻辑电路需要时钟线控制 ,含有记忆性的原件的存在。(只有时钟信号才能工作&…...
AI 实战2 - face -detect
人脸检测 环境安装源设置conda 环境安装依赖库 概述数据集wider_face转yolo环境依赖标注信息格式转换图片处理生成 train.txt 文件 数据集展示数据集加载和处理 参考文章 环境 安装源设置 conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/f…...
CentOS vs Ubuntu - 常用命令深度对比及最佳实践指南20250302
CentOS vs Ubuntu - 常用命令深度对比及最佳实践指南 引言 在 Linux 服务器操作系统领域,CentOS 和 Ubuntu 是广泛采用的发行版。它们在命令集、默认工具链及生态系统方面各有特点。本文深入剖析 CentOS 与 Ubuntu 在常用命令层面的异同,并结合实践案例…...
问题修复-后端返给前端的时间展示错误
问题现象: 后端给前端返回的时间展示有问题。 需要按照yyyy-MM-dd HH:mm:ss 的形式展示 两种办法: 第一种 在实体类的属性上添加JsonFormat注解 第二种(建议使用) 扩展mvc框架中的消息转换器 代码: 因为配置类继…...
为AI聊天工具添加一个知识系统 之127 详细设计之68 编程 核心技术:Cognitive Protocol Language 之1
本文要点 要点 今天讨论的题目:本项目(为使用AI聊天工具的两天者加挂一个知识系统) 详细程序设计 之“编程的核心技术” 。 source的三个子类(Instrument, Agent, Effector) 分别表示--实际上actually ,…...
多个pdf合并成一个pdf的方法
将多个PDF文件合并优点: 能更容易地对其进行归档和备份.打印时可以选择双面打印,减少纸张的浪费。比如把住宿发票以及滴滴发票、行程单等生成一个pdf,双面打印或者无纸化办公情况下直接发送给财务进行存档。 方法: 利用PDF24 Tools网站 …...
周边游平台设计与实现(代码+数据库+LW)
摘 要 在如今社会上,关于信息上面的处理,没有任何一个企业或者个人会忽视,如何让信息急速传递,并且归档储存查询,采用之前的纸张记录模式已经不符合当前使用要求了。所以,对旅游信息管理的提升,…...
深入解析Crawl4AI:为AI应用量身定制的高效开源爬虫框架
引言 在当今数据驱动的时代,人工智能(AI)和大型语言模型(LLM)的发展对高质量数据的需求日益增长。如何高效地从互联网上获取、处理和提取有价值的数据,成为了研究人员和开发者面临的关键挑战。Crawl4AI作为…...
python量化交易——金融数据管理最佳实践——qteasy创建本地数据源
文章目录 qteasy金融历史数据管理总体介绍本地数据源——DataSource对象默认数据源查看数据表查看数据源的整体信息最重要的数据表其他的数据表 从数据表中获取数据向数据表中添加数据删除数据表 —— 请尽量小心,删除后无法恢复!!总结 qteas…...
Python标准库【os】5 文件和目录操作2
文章目录 8 文件和目录操作8.7 浏览目录下的内容8.8 查看文件或目录的信息8.9 文件状态修改文件标志位文件权限文件所属用户和组其它 8.10 浏览Windows的驱动器、卷、挂载点8.11 系统配置信息 os模块提供了各种操作系统接口。包括环境变量、进程管理、进程调度、文件操作等方面…...
⭐算法OJ⭐矩阵的相关操作【动态规划 + 组合数学】(C++ 实现)Unique Paths 系列
文章目录 62. Unique Paths动态规划思路实现代码复杂度分析 组合数学思路实现代码复杂度分析 63. Unique Paths II动态规划定义状态状态转移方程初始化复杂度分析 优化空间复杂度状态转移方程 62. Unique Paths There is a robot on an m x n grid. The robot is initially lo…...
【Java基础】Java中new一个对象时,JVM到底做了什么?
Java中new一个对象时,JVM到底做了什么? 在Java编程中,new关键字是我们创建对象的最常用方式。但你是否想过,当你写下new MyClass()时,Java虚拟机(JVM)到底在背后做了哪些工作?今天&…...
Baklib云内容中台的核心架构是什么?
云内容中台分层架构解析 现代企业内容管理系统的核心在于构建动态聚合与智能分发的云端中枢。以Baklib为代表的云内容中台采用三层架构设计,其基础层为数据汇聚工具集,通过标准化接口实现多源异构数据的实时采集与清洗,支持从CRM、ERP等业务…...
一个基于vue3的图片瀑布流组件
演示 介绍 基于vue3的瀑布流组件 演示地址: https://wanning-zhou.github.io/vue3-waterfall/ 安装 npm npm install wq-waterfall-vue3yarn yarn add wq-waterfall-vue3pnpm pnpm add wq-waterfall-vue3使用 <template><Waterfall :images"imageList&qu…...
内存中的缓存区
在 Java 的 I/O 流设计中,BufferedInputStream 和 BufferedOutputStream 的“缓冲区”是 内存中的缓存区(具体是 JVM 堆内存的一部分),但它们的作用是优化数据的传输效率,并不是直接操作硬盘和内存之间的缓存。以下是详…...
