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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Mark】记录用宝塔+Nginx+worldpress+域名遇到的跨域,301,127.0.0.1,CSS加载失败问题

背景 想要用宝塔搭建worldpress&#xff0c;然后用域名直接转https&#xff0c;隐藏掉ipport。 结果被折磨了1天&#xff0c;一直在死活在301&#xff0c;127.0.0.1打转 还有css加载不了的情况 因为worldpress很多是301重定向的&#xff0c;所以改到最后我都不知道改了什么&am…

0x03 http协议和分层架构

HTTP协议 简介 Hyper Text Transfer Protocol&#xff0c;超文本传输协议&#xff0c;规定了浏览器和服务器之间数据传输的规则 http协议基于TCP协议&#xff1a;面向连接&#xff0c;安全基于请求-响应模型&#xff1a;一次请求对应一次响应HTTP协议是无状态的协议&#xff…

汽车小助手智能体

汽车小助手&#xff1a;智能驱动汽车服务新体验 链接&#xff1a;文心智能体平台AgentBuilder | 想象即现实 文心智能体平台AgentBuilder&#xff0c;是百度推出的基于文心大模型的智能体平台&#xff0c;支持广大开发者根据自身行业领域、应用场景&#xff0c;选取不同类型的…

20250225-代码笔记03-class CVRPModel AND other class

文章目录 前言一、class CVRPModel(nn.Module):__init__(self, **model_params)函数功能函数代码 二、class CVRPModel(nn.Module):pre_forward(self, reset_state)函数功能函数代码 三、class CVRPModel(nn.Module):forward(self, state)函数功能函数代码 四、def _get_encodi…

十一、大数据治理平台总体功能架构

大数据治理平台的功能架构图中心主题&#xff1a;数据治理 核心重点是建立健全大数据资产管理框架&#xff0c;确保数据质量、安全性、可访问性和合规性。 大数据治理平台总体功能架构图 关键功能领域 1.数据资产平台&#xff08;左侧&#xff09; 此部分主要关注数据资产本身…

算法与数据结构(相交链表)

题目 思路 1.哈希集合 因为要求是否存在相交节点&#xff0c;那么我们就可以利用哈希集合先将listA链表里面的所有数据存入&#xff0c;然后访问listB&#xff0c;判断其是否有节点在哈希集合中&#xff0c;若存在&#xff0c;则说明此节点为相交的节点。若遍历完之后仍没有发…

git和gitee在idea中的使用

1.下载git 2.注册一个gitee且创建一个项目 3.在idea的plunge中下在gitee 4.登录gitee 别人使用的话复制 粘贴 commit提交到本地仓库 push推送到云端仓库

yolov8,yolo11,yolo12 服务器训练到部署全流程 笔记

正在进行中&#xff0c;随时更新 一. Anaconda配置 1.安装anaconda (1)下载.sh文件 Index of /anaconda/archive/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror (2)scp到服务器后&#xff0c;运行安装包 bash Anaconda3-2020.07-Linux-x86_64.sh (3)安装anacond…

4.3MISC流量分析练习-wireshark-https

流量分析题目的例题 1.了解wireshark的过滤方式 2.了解tls跟ssl协议基本还原 3.了解xor基本变换方式&#xff0c;获取flag 附件是一个流量包&#xff0c;打开之后有各种流量&#xff0c;但是分析无果&#xff0c;然后丢到kali中使用binwalk进行分析&#xff0c;发现有一个r…

【开源免费】基于SpringBoot+Vue.JS网络海鲜市场系统(JAVA毕业设计)

本文项目编号 T 222 &#xff0c;文末自助获取源码 \color{red}{T222&#xff0c;文末自助获取源码} T222&#xff0c;文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…

【java】@Transactional导致@DS注解切换数据源失效

最近业务中出现了多商户多租户的逻辑&#xff0c;所以需要分库&#xff0c;项目框架使用了mybatisplus所以我们自然而然的选择了同是baomidou开发的dynamic.datasource来实现多数据源的切换。在使用初期程序运行都很好&#xff0c;但之后发现在调用com.baomidou.mybatisplus.ex…

Solana 核心概念全解析:账户、交易、合约与租约,高流量区块链技术揭秘!

目录 1.Solana 核心概念简述 1.1. 账户&#xff08;Account&#xff09; 1.2. 交易&#xff08;Transaction&#xff09; 1.3. 交易指令&#xff08;Instruction&#xff09; 1.4. SPL 代币 1.5. 合约&#xff08;Program&#xff09; 1.6. 租约&#xff08;Rent&#x…

StarRocks 在爱奇艺大数据场景的实践

作者&#xff1a;林豪&#xff0c;爱奇艺大数据 OLAP 服务负责人 小编导读&#xff1a; 本文整理自爱奇艺工程师在 StarRocks 年度峰会的分享&#xff0c;介绍了爱奇艺 OLAP 引擎演化及引入 StarRocks 后的效果。 在广告业务中&#xff0c;StarRocks 替换 ImpalaKudu 后&#x…

【Linux】Linux的进程控制

目录 1. 学习思维导图 2.进程创建&#xff08;fork&#xff09; 2.1 fork创建进程失败 3.进程终止 3.1 进程退出情况 3.1.1main函数 3.1.2 退出码 3.2 exit/_exit函数 1. exit() 函数 2. _exit() 函数 4.进程等待 4.1 实现进程等待的方法 wait/waitpid方法 区别&a…

ubuntu防火墙iptables

文章目录 步骤开启自启防火墙iptables规则链Chains的区别 在 Ubuntu 上使用 iptables 配置防火墙并保证服务可用 步骤 #防火墙状态 systemctl status iptables systemctl start iptables #开启防火墙并且开启22端口 systemctl start iptables && iptables -A INPUT -p…

计算机毕业设计SpringBoot+Vue.js公司日常考勤系统(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

企业微信里可以使用的企业内刊制作工具,FLBOOK

如何让员工及时了解公司动态、行业资讯、学习专业知识&#xff0c;并有效沉淀企业文化&#xff1f;一份高质量的企业内刊是不可或缺的。现在让我来教你该怎么制作企业内刊吧 1.登录与上传 访问FLBOOK官网&#xff0c;注册账号后上传排版好的文档 2.选择模板 FLBOOK提供了丰富的…

Hive-01之数仓、架构、数据类型、DDL、内外部表

一、主题 hive的核心概念hive与数据库的区别hive的架构原理hive的安装部署hive的交互式方式hive的数据类型hive的DDL语法操作 二、要点 1.数据仓库的基本概念 1.数据仓库的基本概念 英文名称为Data Warehouse&#xff0c;可简写为DW或DWH。数据仓库的目的是构建面向分析的…

【Markdown 语法简洁讲解】

Markdown 语法简洁语法讲解 什么是 Markdown1. 标题2. 列表3.文本样式4. 链接与图片5. 代码6. 表格7. 分割线8. 流程图9. 数学公式10. 快捷键11. 字体、字号与颜色 什么是 Markdown Markdown 是一种轻量级标记语言&#xff0c;通过简单的符号实现排版格式化&#xff0c;专注于…

数据如何安全“过桥”?分类分级与风险评估,守护数据流通安全

信息化高速发展&#xff0c;数据已成为企业的核心资产&#xff0c;驱动着业务决策、创新与市场竞争力。随着数据开发利用不断深入&#xff0c;常态化的数据流通不仅促进了信息的快速传递与共享&#xff0c;还能帮助企业快速响应市场变化&#xff0c;把握商业机遇&#xff0c;实…