小tips: 页面链接跳转历史URL不记录的兼容处理

一、跳转历史URL不记录需求的由来

上上篇文章“JS获取上一访问页面URL地址document.referrer实践”提到左上角的返回链接按钮,有了document.referrer为空时候的返回首页处理看上去一切都完美了,但是,实际的交互场景总是错综复杂千变万化的,于是,就有了下面这个尴尬的体验问题。

比方说我们点击首页的“分类”进入分类页,如下图:

分类进入入口

然后分类页头部有个“男生”“女生”的频道切换:

男生女生频道示意

这两个都是直接的链接,如果就会带来这么一个问题,如果用户在“男生”“女生”的频道之间反复切换,则当我们点击左上角的返回按钮(如下图)的时候,就会发现点击很多次还是在“分类页”上(仅仅频道不一样),这其实是不符合用户预期的。

左上角的返回按钮

正常的用户预期应该是点击左上角的返回按钮应该直接回到首页,而不是还在当前页过家家。也就是,虽然技术层面用户刚才的上一页就是“男生”或是“女生”频道页面,但是,我们展现给用户的交互必须是首页。

好的产品就是应该在各个细节上精益求精,因此,虽然这个看似无伤大雅的体验问题被我们前端主动承担,对,主动承担,没有产品经理在后面嘟嘟嘟,而是我们自己给自己加了个需求,就是“男生”“女生”频道切换的时候,URL地址不要进入历史URL记录堆栈。

二、location.replace()方法

我琢磨了下,阻止按钮的默认跳转,然后使用location.replace()替换当前按钮地址应该可行,于是,有了类似下面的处理:

$('#header nav a').on('click', function (event) {
    event.preventDefault();
    location.replace(this.href);
})

电脑测试OK,手机打开Safari测试OK,好开心,感觉应该就可以了。

就跟大boss不可能一招就被灭掉一样,如果真的这么顺利你觉得我会写这篇文章吗?

后来,我使用iOS上的Chrome浏览器一测试,晴天霹雳从天而降,整个人瞬间就不好了,因为点击返回的时候,好像永远就在当前页刷新,返不回去了!感觉比原来体验还要惨,至少一开始总会回到首页。

所以,开始寻求其他解决之道。

三、history.replaceState()和location.replace()方法双管齐下

后来,我的同事成荣通过google在一个隐蔽的地方发现了一个处理手段,然后一整合再一测试,你猜怎么着?嘿,居然就成了。就是下面这般处理的:

$('#header nav a').on('click', function (event) {
    event.preventDefault();
    history.replaceState(null, document.title, this.href.split('#')[0] + '#');
    location.replace('');
})

逻辑如下:

  1. 首先通过HTML5 history.replaceState()方法把当前URL地址替换成以个井号#结尾的目前链接地址;
  2. 执行location.replace('')刷新当前地址(此时#会忽略);

此时,iOS下的Chrome浏览器下无论“男生”“女生”频道怎么切换,点击返回按钮都是回到之前的页面(如本示例的首页)。而之前原本OK的浏览器也依然OK,于是,需求完美解决,各种跳转逻辑更加自然无感知了。

为什么这么曲线救国就可以了呢?我也不清楚,反正就这么成了。

四、页面链接跳转历史URL不记录的兼容处理

上面双管齐下方法只是解决了移动端项目的这个需求,history.replaceState从IE10才开始支持,如果是PC端项目如果也有类似需求,则上面的代码就不适用,于是,我们有必要整一份所有浏览器都兼容的页面链接跳转历史URL不记录的JS代码片段。

如下fnUrlReplace方法:

var fnUrlReplace = function (eleLink) {
    if (!eleLink) {
        return;
    }
    var href = eleLink.href;
    if (href && /^#|javasc/.test(href) === false) {
        if (history.replaceState) {
            history.replaceState(null, document.title, href.split('#')[0] + '#');
            location.replace('');
        } else {
             location.replace(href);
        }
    }
};

其中eleLink参数表示<a>链接DOM元素,理论上,fnUrlReplace()方法兼容到IE6。

要想实现最终的效果,还需要和事件关联。举个简单的例子,假设页面上有个<a>链接,希望点击的时候不进入历史记录堆栈,则可以这样:

document.getElementsByTagName('a')[0].onclick = function (event) {
    if (event && event.preventDefault) {
        event.preventDefault();
    }
    fnUrlReplace(this);
    return false;
};

眼见为实,您可以狠狠地点击这里:起始页进入页面a

点击进入起始页,类似进入起点移动站首页,然后点进去就是一个a/b循环页面,此时,无论是a页面还是b页面,点击返回,会发现都是回到起始页,而非原路径返回。

五、末了的结束语

说到返回按钮,我就不经意看了下新浪微博私信页面的返回按钮的结构,结果:

新浪微博私信返回

先不说点击区域就那么丢丢小,你这图标都不在元素的可视尺寸的中间是闹哪样,难道心里头就不觉得难受吗?

不过这件事情让我有了更深的认识。

这微博的产品体验做的真不咋样,基本上要找反例新浪微博一找一个准,但是,你看,人家的营收,人家的股价,直接超越鼻祖twitter了:

新浪微博股价超twitter

这说明什么,说明咱们做前端,千万不要高估自己在整个公司整个产品周期中的价值,好刀用在刀刃上,你辛辛苦苦加班加点用户体验做到世界第一,如果没有其他领域优秀同事的支持(如运营,市场,销售等),贡献也就杯水车薪,孤芳自赏而已。

说得我自己都开始怀疑人生了,你说,我辛辛苦苦花时间连需求都没提的情况下优化返回跳转的细节体验问题到底有什么意义呢?

这其实跟找对象一样,找了个女朋友,觉得好像就这样,分了,又找了个,结果一相处才发现比自己还败家,才发现原配的好。

用户体验也是类似的。用户是用我们起点web app移动站看小说,就使用嘛,该干嘛干嘛,好像没什么,此时,我们的那些细节体验优化其实用户是感觉不到的。但是,一旦用户再使用其他竞品站点,比方说掌阅,虽然对方渠道强,但是,一使用,哎哟喂,这里不顺,那里咯噔,就会发现还是起点用得好。

所以,在我看来用户体验的价值在当存在同类竞品时候会放得比较大,比方说当初的滴滴和快滴,谁体验好谁优势明显。并且用户体验价值的体现是缓慢深沉但同时足够深远的,大浪淘沙,随着时间的流逝,会逐渐彰显其价值所在。

这就像每天点滴的学习一样,时间久了才会彰显其价值。

如果总想立竿见影,总想找捷径,很大概率在以后的岁月会被超越而且越甩越远。

渐行渐远

(本篇完)

分享到:

标签: , , , , , ,

赞助商广告(我也要赞助)



发表评论(目前21 条评论)

  1. 卧槽,有点看不懂。

  2. 小问题求助大神指点说道:

    <input type="number" value="” name=”count”>

    <a href="pro?action=updateCart&cartid=&pid= ” target=”_top”>修改

    我想点击链接就得到number改变后的值,但是在后台得到的是value中的值 我该怎么做?求助大神

  3. csq233说道:

    我的链接到页面b之后就点不了了

  4. 贾皓丰说道:

    学习学习,滴水穿石

  5. 栗子说道:

    非常赞同

  6. 栗子说道:

    赞!

  7. 我是忠实粉丝说道:

    ‘好的产品就是应该在各个细节上精益求精’,非常的赞同

  8. bestRenekton说道:

    鱼哥。。。这里的返回a标签,url设置成index.html不是一样的效果吗。。。

  9. 小白努力学习中说道:

    请问这个正则语句里的javasc是什么意思?

    /^#|javasc/.test(href)

  10. Kyrie说道:

    每次看大大的文章都有一种醍醐灌顶的感觉。

  11. 二少说道:

    之前就对“男生-女生“这个地方有疑问,想知道为什么两个都做成链接,因为之前做的类似tab原理都是通过display控制显隐,用链接做有什么含义吗

  12. meepo说道:

    从前端到哲学。

  13. west说道:

    研究的好仔细,赞!,后面的用户体验确实是说的那样,有竞争才会优化,没竞争感觉不到哪个好

  14. tians说道:

    沙发

  15. Sebastian Blade说道:

    最后几段说的很有道理

  16. DOMEIGANBATTE说道:

    每次都能学到一些有意思的东西呀~