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 生成的完整目录如下

plugindemo

src​​​​​

mainWeixinMp

6 打包生成的目录

mp-weixin-pack-plugin

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.navigateTouni.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地址并渲染页面

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/25926.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RabbitMQ 的介绍与使用

一. 简介 1> 什么是MQ 消息队列&#xff08;Message Queue&#xff0c;简称MQ&#xff09;&#xff0c;从字面意思上看&#xff0c;本质是个队列&#xff0c;FIFO先入先出&#xff0c;只不过队列中存放的内容是message而已。 其主要用途&#xff1a;不同进程Process/线程T…

对比Grok3 普通账户与 30 美元 Super 账户:默认模式、Think 和 DeepSearch 次数限制以及如何升级

面对这个马斯克旗下的"最聪明"的人工智能&#xff0c;很多人都不知道他们的基本模式&#xff0c;本期将从几个方面开始说明&#xff1a; Grok3的背景与功能 账户类型及其详细背景 使用限制 使用限制对比表 如何充值使用 Super 账户 纯干货&#xff0c;带你了解…

【含文档+PPT+源码】基于过滤协同算法的旅游推荐管理系统设计与实现

项目介绍 本课程演示的是一款基于过滤协同算法的旅游推荐管理系统设计与实现&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含&#xff1a;项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本套系…

牛客NC288803 和+和

​import java.util.Comparator;import java.util.PriorityQueue;import java.util.Scanner;​public class Main {public static void main(String[] args) {// 创建Scanner对象用于读取输入Scanner sc new Scanner(System.in);// 读取两个整数n和m&#xff0c;分别表示数组的…

【uniapp原生】实时记录接口请求延迟,并生成写入文件到安卓设备

在开发实时数据监控应用时&#xff0c;记录接口请求的延迟对于性能分析和用户体验优化至关重要。本文将基于 UniApp 框架&#xff0c;介绍如何实现一个实时记录接口请求延迟的功能&#xff0c;并深入解析相关代码的实现细节。 前期准备&必要的理解 1. 功能概述 该功能的…

DeepSeek能画流程图吗?分享一种我正在使用的DeepSeek画流程图教程

‍‌​​‌‌​‌​‍‌​​​‌‌​​‍‌​​​‌​‌​‍‌​​‌​​‌​‍‌​‌‌‌‌​​‍‌​‌​‌‌​​‍‌​​​‌‌‌‌‍‌​‌‌​‌‌‌‍‌‌​​‌​‌​‍‌​​‌‌​‌‌‍‌​​​‌​‌​‍‌​‌‌‌​‌‌‍‌‌​​‌‌‌‌‍‌​‌‌‌​​​‍‌…

基于Electron的应用程序安全测试基础 — 提取和分析.asar文件的案例研究

目录&#xff1a; 4.4. 案例研究 4.4.2. 情况描述 4.4.3. 信息收集 4.4.3.2. 检查隐藏目录&#xff08;点目录&#xff09;的可能性 4.4.3.3. 使用 DB Browser for SQLite 打开 .db 文件 4.4.3.4. 寻找加密算法 4.4.3.5. 找到加密算法 4.4.3.6. 理解加密流程 4.4.3.7. 找到“Ke…

代码随想录算法训练day64---图论系列8《拓扑排序dijkstra(朴素版)》

代码随想录算法训练 —day64 文章目录 代码随想录算法训练前言一、53. 117. 软件构建—拓扑排序二、47. 参加科学大会---dijkstra&#xff08;朴素版&#xff09;总结 前言 今天是算法营的第64天&#xff0c;希望自己能够坚持下来&#xff01; 今天继续图论part&#xff01;今…

WPF中对滚动条进行平滑滚动

有时候我们在动态添加内容时&#xff0c;需要将滚动条滚动到指定内容处。 一般我们会调用ScrollViewer的ScrollToVerticalOffset&#xff08;垂直方向&#xff09;函数和ScrollToHorizontalOffset&#xff08;水平方向&#xff09;函数来控制滚动条滚动到指定位置。 正常滚动效…

Python 课堂点名桌面小程序

一、场景分析 闲来无事&#xff0c;老婆说叫我开发一个课堂点名桌面小程序&#xff0c;给她在课堂随机点名学生问问题。 人生苦短&#xff0c;那就用 Python 给她写一个吧。 二、依赖安装 因为要用到 excel&#xff0c;所以安装两个依赖&#xff1a; pip install openpyxl…

设计模式——过滤器模式在 Spring 中的实践

设计模式——过滤器模式在 Spring 中的实践 基础介绍模块介绍简单实现业务落地额外问题 基础介绍 过滤器模式&#xff08;Filter Pattern&#xff09;&#xff0c;也称为标准模式&#xff08;Criteria Pattern&#xff09;&#xff0c;是结构型设计模式之一&#xff0c;旨在通…

Linux网络 数据链路层

在Linux网络中&#xff0c;数据链路层位于物理层之上&#xff0c;网络层之下&#xff0c;其主要职责是将网络层的IP数据包封装成帧&#xff0c;并通过物理链路发送到目标设备。同时&#xff0c;它还负责接收来自物理层的帧&#xff0c;并将其解封装为数据包&#xff0c;传递给网…

Java 调试模式下 Redisson 看门狗失效

一、场景分析 前几天在做分布式锁测试&#xff1a; 在调试模式下&#xff0c;lock.lock() 之后打上断点&#xff0c;想测试一下在当前线程放弃锁之前&#xff0c;别的线程能否获取得到锁。 发现调试模式下&#xff0c;看门狗机制失效了&#xff0c;Redis 上 30 秒后&#xff0…

ktransformers 上的 DeepSeek-R1 671B open-webui

ktransformers 上的 DeepSeek-R1 671B open-webui 一、下载GGUF模型1. 创建目录2. 魔塔下载 DeepSeek-R1-Q4_K_M3. 安装显卡驱动和cuda4. 显卡 NVIDIA GeForce RTX 4090 二、安装ktransformers1. 安装依赖2. 安装uv工具链3. 下载源码4. 创建python虚拟环境 三、编译ktransforme…

线性模型 - 支持向量机

支持向量机&#xff08;SVM&#xff09;是一种用于分类&#xff08;和回归&#xff09;的监督学习算法&#xff0c;其主要目标是找到一个最佳决策超平面&#xff0c;将数据点分为不同的类别&#xff0c;并且使得分类边界与最近的数据点之间的间隔&#xff08;margin&#xff09…

html中的元素(2)

在用块级元素完成网页的组织和布局以后&#xff0c;要为其中的每一个小区块添加内容&#xff0c;就需要用到行内元素&#xff1a; 1.字体样式元素 <!DOCTYPE html> <html> <head><meta charset"utf-8"><title>HTML5 保留的文本格式元…

Pytorch中的主要函数

目录 一、torch.manual_seed(seed)二、torch.cuda.manual_seed(seed)三、torch.rand(*size, outNone, dtypeNone, layouttorch.strided, deviceNone, requires_gradFalse)四、给大家写一个常用的自动选择电脑cuda 或者cpu 的小技巧五、torch.version.cuda&#xff1b;torch.bac…

php特性

文章目录 函数特性匹配数组报错进制转换绕过正则表达式匹配换行绝对路径绕过 弱类型语言隐式转换核心概念转换规则 运算符优先级 函数特性 匹配数组报错 以此为例&#xff0c;如果传入参数是一个数组&#xff0c;则preg_match()函数报错返回0&#xff0c;完成绕过&#xff0c;…

HVAC 设计:使用 Ansys Discovery 探索更好的设计

通过 Ansys Discovery 及其 2025 年新功能利用 CFD&#xff0c;通过 Computational Insights 应对 HVAC 行业的挑战。 挑战 HVAC 行业在设计高效可靠的管道系统方面面临多项挑战&#xff1a; 压力损失&#xff1a;设计不当的管道会增加能耗并降低热性能。复杂的几何形状&…

Android实现漂亮的波纹动画

Android实现漂亮的波纹动画 本文章讲述如何使用二维画布canvas和camera、矩阵实现二、三维波纹动画效果&#xff08;波纹大小变化、画笔透明度变化、画笔粗细变化&#xff09; 一、UI界面 界面主要分为三部分 第一部分&#xff1a;输入框&#xff0c;根据输入x轴、Y轴、Z轴倾…