Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

使用pushState实现微信“返回”按钮控制单页应用页面的无刷新跳转 #4

Open
SimonZhangITer opened this issue Feb 20, 2017 · 6 comments

Comments

@SimonZhangITer
Copy link
Owner

SimonZhangITer commented Feb 20, 2017

相信很多微信开发者都会遇到过这样的问题:为了提高用户体验,把多个页面内容放在一个HTML页面进行展示,通过display属性以及transition动画来实现页面的跳转动画,但是点击微信顶部的“返回”按键之后就会直接跳出整个页面。

所以针对以上的情况,一般的应用的解决方案都是在页面的顶部自己画一个导航栏,需要点击自定义的导航栏来实现返回效果。

弊端

但是不觉得和微信的导航栏放在一起,并且微信上面也有返回,两个返回很别扭吗?

并且对于安卓用户来说,底部的返回键岂不是没用了?万一手抖点到了怎么办?

没关系,使用history可以解决:

History

我们知道,浏览器的跳转以及返回都是存在history历史里面的,它是栈,后进先出。
跳转一个新页面就进栈一个,返回一次就出栈一个。所以我们可以控制它的栈来实现返回的效果

pushState

history提供了一个方法pushState,可以手动的添加页面进栈。

使用语法:history.pushState(state, title, url);

  • state:Object,与要跳转到的URL对应的状态信息。
  • title:页面名字,方便调试。
  • url:要跳转到的URL地址,不能跨域,对于单页应用来说没用,传空即可。

如:

history.pushState({
     "page": "productList"
 }, "首页", "");

##replaceState
用新的state和URL替换当前。不会造成页面刷新。语法和pushState相同,该方法一般在首页使用,更改一下首页的参数名,方便监控和判断。

onpopstate

history.go和history.back(包括用户按浏览器历史前进后退按钮)触发,并且页面无刷的时候(由于使用pushState修改了history)会触发popstate事件,事件发生时浏览器会从history中取出URL和对应的state对象替换当前的URL和history.state。通过event.state也可以获取history.state。

window.onpopState = function(){
	var json = window.history.state;//获取当前所在的state
    if (json && json.page == "home") { //page即是pushState时设置的参数
        if (searchParams.sourceUrl && !selected) {
            history.go(-1);
        } else {
            document.querySelector('.product-page').removeCls('show');
            document.querySelector(".visit-hospital-page").classList.remove("show");
        }
    }}

history.go

使用该方法即可实现出栈

history.go(-1);//返回一个页面
history.go(-2);//返回两个页面
以此类推

结合以上所述,即可实现页面的无刷新跳转,希望对大家有帮助

@yajore
Copy link

yajore commented Feb 22, 2017

你这样有个问题,就是微信的浏览器的标题不会更改,我这个bug一直没解决(document.title我忘记是在苹果还是安卓上是无效的),上次看到有个人通过iframe的方式实现了,还没去弄,你可以试着找下,把你这个方法实现完美

@SimonZhangITer
Copy link
Owner Author

@yajore 你说的对,关于微信在ios上面的标题问题,我之前也研究过,使用iframe也解决不了,有点头疼...

@Liqihan
Copy link

Liqihan commented Feb 22, 2017

@SimonZhangITer 微信在ios上的标题,我试过是可以的,也是使用iframe
document.title = title;
var mobile = navigator.userAgent.toLowerCase();
// 针对微信
if (/iphone|ipad|ipod/.test(mobile)) {
var iframe = document.createElement('iframe');
iframe.style.display = 'none';
// 替换成站标favicon路径或者任意存在的较小的图片即可
iframe.setAttribute('src', 'logo.png');
var iframeCallback = function () {
setTimeout(function () {
iframe.removeEventListener('load', iframeCallback);
document.body.removeChild(iframe);
}, 0);
};
iframe.addEventListener('load', iframeCallback);
document.body.appendChild(iframe);
}
这篇文章的方法我昨天试验过,是可以的,但是在ios上有个问题,如果什么都不做,返回还是跳出页面的,但是触碰页面之后就可以指定返回到指定页面去了,不知道是不是bug,楼主有空可以交流下,

@SimonZhangITer
Copy link
Owner Author

@Liqihan 奇了怪了,咱俩写的代码一样一样的,但是我记得我之前测试不行的呀-.-

function wxSetTitle(title) {
    document.title = title;
    var mobile = navigator.userAgent.toLowerCase();
    if (/iphone|ipad|ipod/.test(mobile)) {
        var iframe = document.createElement('iframe');
        iframe.style.visibility = 'hidden';
        iframe.setAttribute('src', 'loading.png');
        var iframeCallback = function() {
            setTimeout(function() {
                iframe.removeEventListener('load', iframeCallback);
                document.body.removeChild(iframe);
            }, 0);
        };
        iframe.addEventListener('load', iframeCallback);
        document.body.appendChild(iframe);
    }
}

@Liqihan
Copy link

Liqihan commented Feb 22, 2017

@SimonZhangITer 会不会是iframe src的问题,我完整的图片地址没贴出来,微信很坑的,我们的图片地址放在阿里云的cdn上,还因此被微信给封过,既然代码一样,我想问题会不会出在这里,仅供参考,

@xymingjun
Copy link

onpopState 中的 s 是小写 -_-||

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants