Uniapp开发微信小程序插件的一些心得

news2025/5/14 20:21:30

一、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.js



import { 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.coloradmin.cn/o/2308239.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Pikachu

一、网站搭建 同样的&#xff0c;先下载安装好phpstudy 然后启动Apache和Mysql 然后下载pikachu&#xff0c;解压到phpstudy文件夹下的www文件 然后用vscode打开pikachu中www文件夹下inc中的config.inc.php 将账户和密码改为和phpstudy中的一致&#xff08;默认都是root&…

CentOS7 使用 YUM 安装时报错:Cannot find a valid baseurl for repo: base/7/x86_64的解决方法

CentOS7 使用 YUM 安装时报错&#xff1a;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.…

Linux----网络通信

一、IP地址详解 &#xff08;一&#xff09;核心概念 概念说明IP地址网络设备的唯一逻辑标识符&#xff0c;相当于网络世界的"门牌号"主机任何接入网络的终端设备&#xff08;计算机/手机/服务器等&#xff09;核心作用① 设备标识 ② 路由寻址 ③ 数据传输 &…

【MySQL篇】数据类型

目录 前言&#xff1a; 1&#xff0c;数据类型的分类 ​编辑 2 &#xff0c;数值类型 2.1 tinyint类型 2.2 bit类型 2.3 小数类型 2.3.1 float类型 2.3.2 decimal类型 3&#xff0c;字符串类型 3.1 char 3.2 varchar 3.3 char与varchar的比较 3.4日期和时间类型 3.5 …

【音视频】图像基础概念

一、图像基础概念 1.1 像素 像素是一个图片的基本单位&#xff0c;pix使英语单词pixtureelement的结合“pixel”的简称&#xff0c;所以像素有图像元素之意。 例如2500*2000的照片就是指横向有2500个像素点&#xff0c;竖向有2000个像素点&#xff0c;总共500万个像素&#x…

时钟树的理解

对应电脑的主板&#xff0c;CPU&#xff0c;硬盘&#xff0c;内存条&#xff0c;外设进行学习 AHB总线 -72MHZ max APB1总线 -36MHZ max APB2-72MHZ max 时序逻辑电路需要时钟线控制 &#xff0c;含有记忆性的原件的存在。&#xff08;只有时钟信号才能工作&…

CentOS vs Ubuntu - 常用命令深度对比及最佳实践指南20250302

CentOS vs Ubuntu - 常用命令深度对比及最佳实践指南 引言 在 Linux 服务器操作系统领域&#xff0c;CentOS 和 Ubuntu 是广泛采用的发行版。它们在命令集、默认工具链及生态系统方面各有特点。本文深入剖析 CentOS 与 Ubuntu 在常用命令层面的异同&#xff0c;并结合实践案例…

问题修复-后端返给前端的时间展示错误

问题现象&#xff1a; 后端给前端返回的时间展示有问题。 需要按照yyyy-MM-dd HH:mm:ss 的形式展示 两种办法&#xff1a; 第一种 在实体类的属性上添加JsonFormat注解 第二种&#xff08;建议使用&#xff09; 扩展mvc框架中的消息转换器 代码&#xff1a; 因为配置类继…

为AI聊天工具添加一个知识系统 之127 详细设计之68 编程 核心技术:Cognitive Protocol Language 之1

本文要点 要点 今天讨论的题目&#xff1a;本项目&#xff08;为使用AI聊天工具的两天者加挂一个知识系统&#xff09; 详细程序设计 之“编程的核心技术” 。 source的三个子类&#xff08;Instrument, Agent, Effector&#xff09; 分别表示--实际上actually &#xff0c;…

多个pdf合并成一个pdf的方法

将多个PDF文件合并优点&#xff1a; 能更容易地对其进行归档和备份.打印时可以选择双面打印&#xff0c;减少纸张的浪费。比如把住宿发票以及滴滴发票、行程单等生成一个pdf&#xff0c;双面打印或者无纸化办公情况下直接发送给财务进行存档。 方法: 利用PDF24 Tools网站 …

周边游平台设计与实现(代码+数据库+LW)

摘 要 在如今社会上&#xff0c;关于信息上面的处理&#xff0c;没有任何一个企业或者个人会忽视&#xff0c;如何让信息急速传递&#xff0c;并且归档储存查询&#xff0c;采用之前的纸张记录模式已经不符合当前使用要求了。所以&#xff0c;对旅游信息管理的提升&#xff0c…

python量化交易——金融数据管理最佳实践——qteasy创建本地数据源

文章目录 qteasy金融历史数据管理总体介绍本地数据源——DataSource对象默认数据源查看数据表查看数据源的整体信息最重要的数据表其他的数据表 从数据表中获取数据向数据表中添加数据删除数据表 —— 请尽量小心&#xff0c;删除后无法恢复&#xff01;&#xff01;总结 qteas…

⭐算法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…

Baklib云内容中台的核心架构是什么?

云内容中台分层架构解析 现代企业内容管理系统的核心在于构建动态聚合与智能分发的云端中枢。以Baklib为代表的云内容中台采用三层架构设计&#xff0c;其基础层为数据汇聚工具集&#xff0c;通过标准化接口实现多源异构数据的实时采集与清洗&#xff0c;支持从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…

【pytest框架源码分析一】pluggy源码分析之hook常用方法

简单看一下pytest的源码&#xff0c;其实很多地方是依赖pluggy来实现的。这里我们先看一下pluggy的源码。 pluggy的目录结构如下&#xff1a; 这里主要介绍下_callers.py, _hooks.py, _manager.py&#xff0c;其中_callers.py主要是提供具体调用的功能&#xff0c;_hooks.py提…

《Kafka 理解: Broker、Topic 和 Partition》

Kafka 核心架构解析:从概念到实践 Kafka 是一个分布式流处理平台,广泛应用于日志收集、实时数据分析和事件驱动架构。本文将从 Kafka 的核心组件、工作原理、实际应用场景等方面进行详细解析,帮助读者深入理解 Kafka 的架构设计及其在大数据领域的重要性。 ​1. Kafka 的背…

在docker容器中运行vllm部署deepseek-r1大模型

# 在本地部署python环境 cd /app/ python -m venv myenv # 激活虚拟环境 source /app/myenv/activate # 要撤销激活一个虚拟环境&#xff0c;请输入: deactivate# 进入虚拟环境安装modelscope pip install modelscope# 下载大模型&#xff08;7B为例&#xff09; modelscope do…

Django基础环境准备

Django基础环境准备 文章目录 Django基础环境准备1.准备的环境 win11系统&#xff08;运用虚拟环境搭建&#xff09;1.1详见我的资源win11环境搭建 2.准备python环境2.1 winr 打开命令提示符 输入cmd 进入控制台2.2 输入python --version 查看是否有python环境2.3在pyhton官网下…

使用DeepSeek实现自动化编程:类的自动生成

目录 简述 1. 通过注释生成C类 1.1 模糊生成 1.2 把控细节&#xff0c;让结果更精准 1.3 让DeepSeek自动生成代码 2. 验证DeepSeek自动生成的代码 2.1 安装SQLite命令行工具 2.2 验证DeepSeek代码 3. 测试代码下载 简述 在现代软件开发中&#xff0c;自动化编程工具如…