为uni-app电脑网页套个手机外壳
问题
在UniAPP发布过程中,你有没有遇到过这种问题:
1. 文字太大了
2. 电脑屏幕看手机页面太丑了
3. 分享链接打开总是首页,没法做分销
解决思路
解决思路一:改变原有样式适应PC浏览器
这种解决思路成本太大,不值得。
解决思路二:让用户用F12查看
不能增加用户的学习成本。
解决思路三:套个手机壳,在手机壳内浏览
这个就是我采用的解决方案。
先来看看效果:
难点
刚开始研究还以为很简单,但研究的时候发现套用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