uniapp webview 与 web页面交互通信

注:本文仅适用于页面使用web网页,原生能力通过事件传递给uniapp壳体触发的项目

创建事件分发器(uniapp壳体)

javascript 复制代码
//模块注册的事件保存类
class EventModule{
	//保存的模块事件
	events = {}
	constructor(){}
	//注册事件
	on(eventName,callback){
	   if(this.events[eventName]) return console.error('事件名已存在!');
	   if(typeof callback !== 'function') return console.error("回调函数类型错误!");
	   //注册模块事件
	   this.events[eventName] = callback;
	}
}

//事件分发器
class EventEmit {
	//组件实例
	instance = null;
	//事件模块集合
	eventMap = new Map();
	//事件集合
	events = null;
	//构造函数
	constructor() {};
	//创建实例
	static init(){
	  if(!EventEmit.instance){
		EventEmit.instance = new EventEmit();	
	  }
	  return EventEmit.instance;
	}
	//获取当前模块的事件
    static initEvents(){
	  //创建事件容器	
	  this.events = new EventModule()
	  //返回容器类
	  return this.events;
	}
	//注册模块
	use(moduleName,module) {
	   if(this.eventMap.get(moduleName)) return console.error("模块名重复!");
	   this.eventMap.set(moduleName,module.events);
	}
	//注册事件
	on(eventName,callback){
	   if(typeof callback !== 'function') return console.error("回调函数类型错误!");
	   //注册模块事件
	   this.events.on(eventName,callback);
	}
	//触发事件
	emit(wv,{ moduleName,eventName,params }){
	  if(!wv) throw new Error('webview尚未加载完成!')
	  if(!this.eventMap.get(moduleName)) return console.error("模块不存在!");
	  //获取模块
	  const module = this.eventMap.get(moduleName);
	  //检查事件是否存在
	  if(!module[eventName]) return console.error("事件不存在!");
	  //触发模块事件
	  module[eventName]({ 
		send:(params)=>{
		  const data = JSON.stringify({ type:'success',data:params })
		  wv.evalJS(`onUniEventListener(${data})`)
	    },
		error:(params)=>{
		  const data = JSON.stringify({ type:'fail',data:params })
		  wv.evalJS(`onUniEventListener(${data})`)
	  }},params);
	}
}

/**
 * 创建类实例
 */
export default EventEmit

首页使用(uniapp壳体)

javascript 复制代码
<template>
  <div class="page">
  <web-view src="http://192.168.x.xxx:8080" //你自己的ip
	 @message="AppEmit"
	 @onPostMessage="AppEmit"
  ></web-view>
  </div>
</template>

<script setup>
import {  ref,onMounted } from "vue";
import { onLoad } from "@dcloudio/uni-app"
import EventEmit from '@/events/index.js'
import bluetoothEmit from "@/events/bluetooth";

//事件分发器实例
const eventEmit = EventEmit.init()

//注册测试模块
eventEmit.use('bluetooth',bluetoothEmit);


const pages = getCurrentPages();
const page = pages[pages.length - 1];
const webview = page.$getAppWebview();

let wv;
setTimeout(()=>{
	wv = webview.children()[0];
},800);


//网页向webview触发事件
const AppEmit = (e)=>{
	//获取h5传过来的事件及参数
	const event = e.detail.data[0];
	//分发事件
	eventEmit.emit(wv,event)
}


</script>

<style scoped lang="scss">
.page {
  padding-top: 60px;
}
</style>

注册模块事件(uniapp壳体)

javascript 复制代码
import initEventEmit from "@/events/index.js";

const bluetoothEmit = initEventEmit.initEvents();

bluetoothEmit.on('test',(res,params)=>{
  console.error('事件触发了',params)
  res.send({ msg:'test发送给h5的消息' })
})
 
export default bluetoothEmit

uni.webview.js(web项目)

在html页面或者main.js中引入uni.webview.js

javascript 复制代码
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e=e||self).uni=n()}(this,(function(){"use strict";try{var e={};Object.defineProperty(e,"passive",{get:function(){!0}}),window.addEventListener("test-passive",null,e)}catch(e){}var n=Object.prototype.hasOwnProperty;function i(e,i){return n.call(e,i)}var t=[];function o(){return window.__dcloud_weex_postMessage||window.__dcloud_weex_}function a(){return window.__uniapp_x_postMessage||window.__uniapp_x_}var r=function(e,n){var i={options:{timestamp:+new Date},name:e,arg:n};if(a()){if("postMessage"===e){var r={data:n};return window.__uniapp_x_postMessage?window.__uniapp_x_postMessage(r):window.__uniapp_x_.postMessage(JSON.stringify(r))}var d={type:"WEB_INVOKE_APPSERVICE",args:{data:i,webviewIds:t}};window.__uniapp_x_postMessage?window.__uniapp_x_postMessageToService(d):window.__uniapp_x_.postMessageToService(JSON.stringify(d))}else if(o()){if("postMessage"===e){var s={data:[n]};return window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessage(s):window.__dcloud_weex_.postMessage(JSON.stringify(s))}var w={type:"WEB_INVOKE_APPSERVICE",args:{data:i,webviewIds:t}};window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessageToService(w):window.__dcloud_weex_.postMessageToService(JSON.stringify(w))}else{if(!window.plus)return window.parent.postMessage({type:"WEB_INVOKE_APPSERVICE",data:i,pageId:""},"*");if(0===t.length){var u=plus.webview.currentWebview();if(!u)throw new Error("plus.webview.currentWebview() is undefined");var g=u.parent(),v="";v=g?g.id:u.id,t.push(v)}if(plus.webview.getWebviewById("__uniapp__service"))plus.webview.postMessageToUniNView({type:"WEB_INVOKE_APPSERVICE",args:{data:i,webviewIds:t}},"__uniapp__service");else{var c=JSON.stringify(i);plus.webview.getLaunchWebview().evalJS('UniPlusBridge.subscribeHandler("'.concat("WEB_INVOKE_APPSERVICE",'",').concat(c,",").concat(JSON.stringify(t),");"))}}},d={navigateTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;r("navigateTo",{url:encodeURI(n)})},navigateBack:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.delta;r("navigateBack",{delta:parseInt(n)||1})},switchTab:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;r("switchTab",{url:encodeURI(n)})},reLaunch:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;r("reLaunch",{url:encodeURI(n)})},redirectTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;r("redirectTo",{url:encodeURI(n)})},getEnv:function(e){a()?e({uvue:!0}):o()?e({nvue:!0}):window.plus?e({plus:!0}):e({h5:!0})},postMessage:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};r("postMessage",e.data||{})}},s=/uni-app/i.test(navigator.userAgent),w=/Html5Plus/i.test(navigator.userAgent),u=/complete|loaded|interactive/;var g=window.my&&navigator.userAgent.indexOf(["t","n","e","i","l","C","y","a","p","i","l","A"].reverse().join(""))>-1;var v=window.swan&&window.swan.webView&&/swan/i.test(navigator.userAgent);var c=window.qq&&window.qq.miniProgram&&/QQ/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var p=window.tt&&window.tt.miniProgram&&/toutiaomicroapp/i.test(navigator.userAgent);var _=window.wx&&window.wx.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var m=window.qa&&/quickapp/i.test(navigator.userAgent);var f=window.ks&&window.ks.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var l=window.tt&&window.tt.miniProgram&&/Lark|Feishu/i.test(navigator.userAgent);var E=window.jd&&window.jd.miniProgram&&/jdmp/i.test(navigator.userAgent);var x=window.xhs&&window.xhs.miniProgram&&/xhsminiapp/i.test(navigator.userAgent);for(var S,h=function(){window.UniAppJSBridge=!0,document.dispatchEvent(new CustomEvent("UniAppJSBridgeReady",{bubbles:!0,cancelable:!0}))},y=[function(e){if(s||w)return window.__uniapp_x_postMessage||window.__uniapp_x_||window.__dcloud_weex_postMessage||window.__dcloud_weex_?document.addEventListener("DOMContentLoaded",e):window.plus&&u.test(document.readyState)?setTimeout(e,0):document.addEventListener("plusready",e),d},function(e){if(_)return window.WeixinJSBridge&&window.WeixinJSBridge.invoke?setTimeout(e,0):document.addEventListener("WeixinJSBridgeReady",e),window.wx.miniProgram},function(e){if(c)return window.QQJSBridge&&window.QQJSBridge.invoke?setTimeout(e,0):document.addEventListener("QQJSBridgeReady",e),window.qq.miniProgram},function(e){if(g){document.addEventListener("DOMContentLoaded",e);var n=window.my;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){if(v)return document.addEventListener("DOMContentLoaded",e),window.swan.webView},function(e){if(p)return document.addEventListener("DOMContentLoaded",e),window.tt.miniProgram},function(e){if(m){window.QaJSBridge&&window.QaJSBridge.invoke?setTimeout(e,0):document.addEventListener("QaJSBridgeReady",e);var n=window.qa;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){if(f)return window.WeixinJSBridge&&window.WeixinJSBridge.invoke?setTimeout(e,0):document.addEventListener("WeixinJSBridgeReady",e),window.ks.miniProgram},function(e){if(l)return document.addEventListener("DOMContentLoaded",e),window.tt.miniProgram},function(e){if(E)return window.JDJSBridgeReady&&window.JDJSBridgeReady.invoke?setTimeout(e,0):document.addEventListener("JDJSBridgeReady",e),window.jd.miniProgram},function(e){if(x)return window.xhs.miniProgram},function(e){return document.addEventListener("DOMContentLoaded",e),d}],M=0;M<y.length&&!(S=y[M](h));M++);S||(S={});var P="undefined"!=typeof uni?uni:{};if(!P.navigateTo)for(var b in S)i(S,b)&&(P[b]=S[b]);return P.webView=S,P}));

创建触发器(web项目)

javascript 复制代码
export default class Events {
  instance = null;
  eventMap = {};
  constructor() {
    if (!Events.instance) {
      Events.instance = this;
    }
    return Events.instance;
  }
  emit(moduleName, options) {
    uni.postMessage({
      data: {
        moduleName: moduleName,
        eventName: options.eventName,
        params: options.data
      }
    });
    //绑定回调事件
    this.eventMap[`${moduleName}-${options.eventName}`] = {
      success: options.success ? options.success : () => {},
      fail: options.fail ? options.fail : () => {}
    };
  }
  on({ type, moduleName, eventName, data }) {
    switch (type) {
      case "success":
        this.eventMap[`${moduleName}-${eventName}`].success(data);
        break;
      case "fail":
        this.eventMap[`${moduleName}-${eventName}`].fail(data);
        break;
    }
  }
}

在入口注册(web项目 通常在main.js)

javascript 复制代码
import EventEmit from "@/system/events";

const eventEmit = new EventEmit();

 //注册uniapp事件
 window.onUniEventListener = (data) => eventEmit.on(data);

页面中使用(web项目)

javascript 复制代码
import EventEmit from "@/system/events";

const eventEmit = new EventEmit();

const emit = () => {
  eventEmit.emit("bluetooth", {
    eventName: "test",
    data: {
      msg: "你在干啥呢?"
    },
    success: (res) => {
      console.log("结果", res);
    },
    fail: (err) => {
      console.log("发生了错误", err);
    }
  });
};
相关推荐
小短腿的代码世界11 小时前
Qt 股票订单撮合引擎:高频交易系统的核心心脏
开发语言·数据库·qt·系统架构·交互
UXbot12 小时前
一人独立交付 UI + 前端:AI 驱动 UI 设计工具的五大功能模块深度评测
前端·低代码·ui·设计模式·交互
莽撞的大地瓜1 天前
蜜度携交通运输行业全链路AI解决方案亮相2026交通科技博览会
交互·交友·交通物流
全球通史1 天前
Jetson Nano语音交互:本地大模型全链路实战
ubuntu·交互
灵机一物1 天前
灵机一物AI原生电商小程序、PC端(已上线)-技术解析:原生实时交互 AI 模型 TML-Interaction-Small,如何颠覆传统大模型交互范式
人工智能·交互
小短腿的代码世界1 天前
QwtPolar 与实时示波器级渲染优化:雷达图到示波器曲线的极限性能调优
前端·qt·架构·交互
ez52fF0k81 天前
.NET11云原生CI/CD在云原生应用持续集成与交付安全加固
前端·c#·交互
北***字2 天前
数字媒体交互设备:构建未来数字创意人才的实训高地
交互·媒体
UXbot2 天前
AI一次生成iOS和Android双端原型功能详解
android·前端·ios·kotlin·交互·swift