话不多说,直接放最终版本代码。
解决思路是:如果设备是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-PLUS
this.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-PLUS
this.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>