为uni-app电脑网页套个手机外壳

问题

在UniAPP发布过程中,你有没有遇到过这种问题:
1. 文字太大了
2. 电脑屏幕看手机页面太丑了
3. 分享链接打开总是首页,没法做分销

解决思路

解决思路一:改变原有样式适应PC浏览器

这种解决思路成本太大,不值得。

解决思路二:让用户用F12查看

不能增加用户的学习成本。

解决思路三:套个手机壳,在手机壳内浏览

这个就是我采用的解决方案。
先来看看效果:
分辨率大于等于600时
分辨率小于600时

难点

刚开始研究还以为很简单,但研究的时候发现套用iframe的时候
1.【子页面需要给父页面传页面跳转的消息】
2.【子页面路由使用的是history的hash模式,父页面改变url会增加history导致跳转错误】

解决方案

父子页面传递消息需要用到window的postMessage方法,具体使用方法可以百度去查,难点在与uniapp是没有路由页面跳转事件的,需要手动去加监听。
网上搜了搜一般用的都是路由组件。这里我知道自己用的是hash模式,所以我可以在history对象上动手脚:

function post(){
	if(self != top)//判断是不是在iframe里,不是就不用推了
		window.parent.postMessage("urlChanged","*");//通知一下就行,父页面直接来子页面拿url
}
var replaceState = window.history.replaceState;
var pushState = window.history.pushState;
window.history.replaceState=function(res){post();replaceState(res);}
window.history.pushState=function(res){post();pushState(res);}

如此修改replaceState与pushState方法加上自己的监听事件岂不美哉?
当然,这样还有个地方没监听到,就是回退。这里我用了onhashchange事件来保证监听得到:

window.onhashchange=function(res){post();}

综合起来就是:

// #ifdef H5
	if(window.innerWidth>=600)
		location.href = "/pc.html"+location.href.substring(location.href.indexOf("#"));
	function post(){
		if(self != top)
			window.parent.postMessage("urlChanged","*");
	}
	var replaceState = window.history.replaceState;
	var pushState = window.history.pushState;
	window.history.replaceState=function(res){post();replaceState(res);}
	window.history.pushState=function(res){post();pushState(res);}
	window.onhashchange=function(res){post();}
// #endif

把这段代码塞到App.vue的onLaunch方法中就行了。如此还不影响它端的发布,舒舒服服。
最终HTML部分的代码(pc.html):

<html>
	<head>
		<style type="text/css">
			#showMobilePreview {
				z-index: 9999;
				width: 387px;
				height: 768px;
				min-height: 396px;
				max-height: calc(100vh - 64px);
				position: absolute;
				left: 50%;
				top: 50%;
				transform: translate(-50%, -50%);
				opacity: 1;
				text-align: center;
				border-radius: 50px;
				box-shadow: -10px 10px 30px #333333;
			}

			.mobile_preview_header {
				display: block;
				position: absolute;
				top: 0;
				left: 0;
				height: 40px;
				width: 387px;
				background: #eeeff2;
				text-align: center;
				line-height: 40px;
				border-top-right-radius: 50px;
				border-top-left-radius: 50px;
			}

			.mobile_preview_header_icon {
				display: inline-block;
				width: 65px;
				height: 10px;
				background: #c8c9cc;
				border-radius: 9px;
				vertical-align: middle;
				margin-top: 18px;
			}

			.mobile_preview_frame {
				width: 375px;
				min-height: 294px;
				height: 667px;
				max-height: calc(100vh - 166px);
				top: 40px;
				left: 0;
				border: 6px solid #eeeff2;
				position: relative;
				background-color: #fff;
				display: block;
			}

			#YuFrameMobilePreview {
				border: none;
				width: 375px;
				height: 100%;
			}

			.mobile_preview_footer {
				display: block;
				position: absolute;
				bottom: 0;
				left: 0;
				height: 52px;
				width: 387px;
				background: #eeeff2;
				text-align: center;
				line-height: 45px;
				border-bottom-right-radius: 50px;
				border-bottom-left-radius: 50px;
			}

			.mobile_preview_footer_icon {
				display: inline-block;
				width: 43px;
				height: 43px;
				background: #c8c9cc;
				border-radius: 50%;
				vertical-align: middle;
			}

			#mobilePreview {
				background: url("mobile-preview.png") no-repeat;
				padding-left: 20px;
				color: #bcbdc1;
			}

			#mobilePreview:hover {
				background: url("mobile-preview-hover.png") no-repeat;
				padding-left: 20px;
				color: #009ddc;
			}
			#YuFrameMobilePreviewBg{
				cursor:pointer;
				width:100%;
				height:100%;
				background-color: Gray;
				display:block;
				z-index:9998;
				position:absolute;
				left:0px;
				top:0px;
				filter:Alpha(Opacity=30);
				/* IE */
				-moz-opacity:0.4;
				/* Moz + FF */
				opacity: 0.4; 
			}
		</style>
	</head>
	<body>
		<div id='showMobilePreview'>
			<div class='mobile_preview_header'>
				<i class='mobile_preview_header_icon'></i>
			</div>
			<div class='mobile_preview_frame'>
				<iframe id='YuFrameMobilePreview' src='/'></iframe>
			</div>
			<div class='mobile_preview_footer'>
				<i class='mobile_preview_footer_icon'></i>
			</div>
		</div>
		<div id='YuFrameMobilePreviewBg'></div>
		<script>
			if(window.outerWidth<600)
				location.href = "/"+location.href.substring(location.href.indexOf("#"));
			if(location.href.indexOf("#")!=-1)
				document.getElementById("YuFrameMobilePreview").contentWindow.location.href = "/"+location.href.substring(location.href.indexOf("#"));
				window.addEventListener('message',function(event){
					if(event.data=="urlChanged"){
						var iframeUrl = document.getElementById("YuFrameMobilePreview").contentWindow.location.href;
						window.history.replaceState(null,null,location.href.split("#")[0] + iframeUrl.substring(iframeUrl.indexOf("#")));
					}
				}, false);
		</script>
	</body>
</html>

参考的页面外壳源博客:https://blog.csdn.net/qq_23853743/article/details/98623159

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值