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

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.lqws.cn/news/150967.html

相关文章:

  • C++学习-入门到精通【14】标准库算法
  • 996引擎-自定义装备/道具:限时装备、限时道具
  • 【Linux】 Linux 进程控制
  • mongodb源码分析session异步接受asyncSourceMessage()客户端流变Message对象
  • elementUI点击浏览table所选行数据查看文档
  • .net Span类型和Memory类型
  • 中国森林地上和地下植被碳储量数据集(2002~2021)
  • 在 Oracle 中,创建不同类型索引的 SQL 语法
  • Neo4j图数据库管理:原理、技术与最佳实践
  • MDK程序调试
  • 五、查询处理和查询优化
  • Spring Boot + Elasticsearch + HBase 构建海量数据搜索系统
  • Spring Boot 缓存注解详解:@Cacheable、@CachePut、@CacheEvict(超详细实战版)
  • 【Linux篇】0基础之学习操作系统进程
  • Selenium 查找页面元素的方式
  • 【hadoop】Flink安装部署
  • 华为OD最新机试真题-小明减肥-OD统一考试(B卷)
  • CLIP多模态大模型的优势及其在边缘计算中的应用
  • mac 电脑Pycharm ImportError: No module named pip
  • opencv如何在仿射变换后保留完整图像内容并自动裁剪
  • 数学建模-嘉陵江铊污染事件解题全过程文档及程序
  • 论文速读《DexWild:野外机器人策略的灵巧人机交互》
  • Uniapp 二维码生成与解析完整教程
  • SpringBoot自动化部署全攻略:CI/CD高效实践与避坑指南
  • 空间利用率提升90%!小程序侧边导航设计与高级交互实现
  • 苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会
  • 钉钉 - 机器人消息推送(签名版)
  • Python Rio 【图像处理】库简介
  • ECB(电子密码本,Electronic Codebook) 和 CBC(密码分组链接,Cipher Block Chaining)区分于用途
  • EXCEL如何快速批量给两字姓名中间加空格