当前位置: 首页 > article >正文

App使用webview套壳引入h5(三)——解决打包为app后在安卓机可物理返回但是在苹果手机无法测滑返回的问题

话不多说,直接放最终版本代码。

解决思路是:如果设备是ios设备在myH5中监听 touchstart 和touchend事件

经过 App使用webview套壳引入h5的最终代码如下
myApp中,entry.vue代码如下:

<template><view class="entry-page" :style="{ paddingTop: safeAreaInsets.top + 'px' }"><web-view :webview-styles="webviewStyles" :src="webviewUrl" @message="getH5Message" ref="webViewRef"></web-view></view>
</template><script>
export default {data() {return {statusBarHeight: 100,safeAreaInsets: {},webviewUrl: 'myLink', hasBottomSafeArea: false,webviewStyles: {progress: {color: '#007aff',top: 0},// iOS侧滑返回配置ios: {allowsBackForwardNavigationGestures: true, // 启用WKWebView侧滑手势bounces: false // 禁用弹性效果}},webview: '',isIOS: false,          // 判断是否为iOS设备webviewCanBack: false  // WebView是否可返回};},onReady() {var currentWebview = this.$scope.$getAppWebview().children()[0];this.webview = currentWebview; // 缓存WebView实例currentWebview.addEventListener('loaded', () => {			currentWebview.evalJS('$("ul.fed-part-rows a[href*=\'resource.i847.cn\']").parent().hide();');});},onLoad(options) {// #ifdef APP-PLUSthis.isIOS = uni.getSystemInfoSync().platform === 'ios'; // 检测iOS设备let _this = this;let height = 0;let statusbar = 0;const sysInfo = uni.getSystemInfoSync();this.safeAreaInsets = sysInfo.safeAreaInsets;console.log('top--------', sysInfo);this.statusBarHeight = sysInfo.statusBarHeight;height = sysInfo.windowHeight;let currentWebview = this.$scope.$getAppWebview();setTimeout(() => {var wv = currentWebview.children()[0];console.log('top--------222222222', _this.statusBarHeight);wv.setStyle({top: _this.statusBarHeight,height: height - _this.statusBarHeight,scalable: false});}, 200);// #endif},onBackPress(e) {// 响应返回事件(关键修改,此处测试发行仅在打包为安卓的情况下可响应onBackPress)if (this.isIOS) {// iOS设备:优先WebView内部返回if (this.webviewCanBack) {this.webview.back(); // WebView返回上一级H5页面return true; // 拦截默认返回}}// 其他情况执行原有逻辑this.webView = this.$mp.page.$getAppWebview().children()[0];this.webView.evalJS('window.getPageUrl()');return true;},methods: {test() {console.log('test webview');},dealBackEvent() {console.log('dealBackEvent webview');},showCurrentPage(pageInfo) {console.log('showCurrentPage', pageInfo);if (pageInfo.pathname) {const targetArray = ['pages/index/index', 'tab页2', 'tab页3'];const processedString = pageInfo.pathname.replace('myLink地址中的页面公共路径', '');const exists = targetArray.includes(processedString);if (exists) {console.log('showCurrentPage ----------1');uni.showModal({title: '提示',content: '确定要退出吗?',success: (res) => {if (res.confirm) {plus.runtime.quit();}}});} else {console.log('showCurrentPage ----------2');// 优先WebView返回(关键修改)if (this.webviewCanBack) {this.webview.back();} else {this.webView.back();}}}},getH5Message(e) {console.log('来自webview的消息*******************', e);var item = e.detail.data[0];switch (item.type) {case 'back':this.operation();break;case 'outApp':this.back();break;case 'isFun':this[item.action](item.message);break;case 'historyChange':// 接收H5历史变化通知(关键修改)this.webviewCanBack = item.data.canBack;break;case 'iosBack':// 接收iOS返回通知(关键修改)if (!item.data.canBack) {uni.navigateBack();}break;default:uni.showToast({title: item.message,duration: 2000});break;}},operation() {// #ifdef APP-PLUSthis.webView = this.$mp.page.$getAppWebview().children()[0];console.log('operation********', this.webView);// #endif},back() {uni.showModal({title: '提示',content: '是否退出系统?',success: function (res) {if (res.confirm) {plus.runtime.quit();} else if (res.cancel) {console.log('用户点击取消');}}});}}
};
</script><style>
.entry-page {background-color: #f8f8f8;
}.webview-container {flex: 1;width: 100%;
}
</style>

myH5项目中
记得引入webviewJs,参考 App使用webview套壳引入h5(一)
App.vue的代码如下

<script>export default {data() {return {isIos: false,transitionName: '', // 过渡动画的名称startPosition: {x: 0,y: 0}, // 手势开始时的位置};},created() {console.log("at app created---0", this.startPosition);// 初始化数据this.startPosition = {x: 0,y: 0};this.isIOS = uni.getSystemInfoSync().platform === 'ios'; // 检测iOS设备console.log("at app created---1", this.startPosition,this.isIOS);},mounted() {console.log("at app mounted---0", this.startPosition);let that = this// 使用$nextTick确保DOM和数据完全初始化后执行this.$nextTick(() => {console.log("at app mounted---1", that.startPosition);console.log("at app mounted---2", that.startPosition.x);// 初始化事件监听that.initEventListeners();});},methods: {// 将事件监听逻辑提取为单独的方法initEventListeners() {if (this.isIOS) {// 监听touchstart事件window.addEventListener('touchstart', (event) => {this.handleTouchStart(event);});// 监听touchend事件window.addEventListener('touchend', (event) => {this.handleTouchEnd(event);});}// 确保uni对象存在后执行初始化this.initUniAppBridge();},// 处理touchstart事件handleTouchStart(event) {this.startPosition.x = event.touches[0].pageX;this.startPosition.y = event.touches[0].pageY;},// 处理touchend事件handleTouchEnd(event) {const endPosition = {x: event.changedTouches[0].pageX,y: event.changedTouches[0].pageY,};// 计算手势滑动的距离const deltaX = endPosition.x - this.startPosition.x;const deltaY = endPosition.y - this.startPosition.y;console.log("touchend---------2");// 判断滑动方向与滑动距离是否符合返回操作的条件if (Math.abs(deltaX) > Math.abs(deltaY) && Math.abs(deltaX) > 30) {if (deltaX > 0) {// 获取当前路由栈的长度const pages = getCurrentPages();const stackLength = pages.length;console.log('[H5] popstate触发,历史长度:', window.history.length, this.$router, stackLength);// 向右滑动,执行返回上一页的操作this.transitionName = 'slide-right';// this.$router.go(-1);uni.navigateBack()}// else if (deltaX < 0) {//         // 向左滑动,执行前进一页的操作//         this.transitionName = 'slide-left';//         this.$router.go(1);//       }}},// 初始化与uni-app的桥接initUniAppBridge() {// 和webview进行网页通信document.addEventListener('UniAppJSBridgeReady', () => {uni.webView.getEnv((res) => {console.log('当前环境:' + JSON.stringify(res));});uni.webView.postMessage({data: {message: '我是来自H5的消息',action: 'test',type: 'isFun'}});});window.getPageUrl = (arg) => {uni.webView.postMessage({data: {action: 'showCurrentPage',message: location,type: 'isFun',}});};},},beforeDestroy() {if (this.isIos) {// 移除所有事件监听window.removeEventListener('touchstart', this.handleTouchStart);window.removeEventListener('touchend', this.handleTouchEnd);}}}
</script><style lang="scss">
</style>
http://www.lryc.cn/news/2403529.html

相关文章:

  • CSS中text-align: justify文本两端对齐
  • 2025年渗透测试面试题总结-ali 春招内推电话1面(题目+回答)
  • C#中的依赖注入
  • Reactor和Proactor
  • 黄晓明新剧《潜渊》定档 失忆三面间谍开启谍战新维度
  • 深入浅出Java ParallelStream:高效并行利器还是隐藏的陷阱?
  • 物联网嵌入式开发实训室建设方案探讨(高职物联网应用技术专业实训室建设)
  • 集成学习三种框架
  • 大数据量高实时性场景下订单生成的优化方案
  • 在UI界面内修改了对象名,在#include “ui_mainwindow.h“没更新
  • ocrapi服务docker镜像使用
  • 使用React+ant Table 实现 表格无限循环滚动播放
  • Podman 和 Docker
  • Neovim - 常用插件,提升体验(三)
  • C++单例模式教学指南
  • SOC-ESP32S3部分:31-ESP-LCD控制器库
  • 如何区分虚拟货币诈骗与经营失败?
  • Flink 高可用集群部署指南
  • 【云安全】以Aliyun为例聊云厂商服务常见利用手段
  • 读文献先读图:GO弦图怎么看?
  • 青少年编程与数学 02-020 C#程序设计基础 16课题、文件操作
  • 怎么让大语言模型(LLMs)自动生成和优化提示词:APE
  • 网关路由配置(Gateway Filters)
  • 实现单例模式的常见方式
  • Go 为何天生适合云原生?
  • 数仓面试提问:在资源(计算、存储、人力)受限的情况下,如何优先处理需求并保证核心交付?
  • 第七十四篇 高并发场景下的Java并发容器:用生活案例讲透技术原理
  • day20 leetcode-hot100-38(二叉树3)
  • Python打卡训练营学习记录Day46
  • 使用 C/C++ 和 OpenCV 实现滑动条控制图像旋转