引言 有一些 H5 开发者耳熟能详的问题。
比如,老板会问你:“你这个 H5 页面为什么这么卡?为啥 IOS 那么流畅?”,
再比如,业务方会问你:“为什么这个功能你做不了?人家 Native 可以做?”,
再再比如,交互甚至也会经常挑战你:“为什么安卓能做到这样的交互效果,你不可以?”。
我只想说,作为 H5 开发,我们是有苦衷的 =,=
心痛的简直无法呼吸。
这个问题确实困扰了挺久 H5 页面中,浏览器/安卓 的 back(返回) 键,默认会直接后退到上一个页面,这听起来似乎十分正常。
但是对于一个以 Web App 为导向的产品来讲,当前习惯 APP 交互操作的用户的第一反应应该会是:如果当前页面有浮层的话,先解散浮层(不管你承不承认,事实如此)。
话不多说直接上图:
点击浏览器回退直接。。。 体验不够好!!!
说实话,关于这个交互的优化,一开始我是拒绝的。
浏览器默认行为!你要我怎样?我即便是改了,有很多副作用你知道吗?history 你能随随便便玩得起?
直到某天灵(kan)机(dao)一(jing)动(pin),有(bei)了(da)头(lian)绪(le)。
我觉得不做不行了 一样的套路,要把大象装冰箱,总共分几步?
第 1 步:浮层被点击唤起时,为 URL Push 一个 Hash 值(要唯一); 第 2 步:浮层被用户通过自定义关闭按钮解散时,主动去掉对应 Hash; 第 3 步:监听hashchange事件,用户点击浏览器/安卓回退按钮时,解散对应浮层(通过唯一 Hash 值匹配),此时 Hash 值会被浏览器默认 pop 掉,这也是点击回退之后浏览器并不回到前一个页面的关键,因为正常的路由并没有变化!!!
Done~
现在看起来就像那么回事了:
当然,还有复杂一点的,嵌套浮层的 case 需要考虑。不过这时候我觉得已经触及我文字表达能力的盲区了 =,=
上代码:
这是我封装好的一个 React 组件 Enback 的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 import React from 'react' ;import PropTypes from 'prop-types' ;class Enback extends React.Component { static defaultProps = { uniqueKey : 'newPop' } static propTypes = { uniqueKey : PropTypes .string } constructor (props ) { super (props); } componentDidMount = () => { const { uniqueKey, popStateCallback } = this .props ; const state = { uniqueKey : uniqueKey }; if (location.hash ) { history.pushState (state, null , `${location.hash} /${uniqueKey} ` ); } else { history.pushState (state, null , `#${uniqueKey} ` ); } window .addEventListener ('hashchange' , function (e ) { const popHash = e.oldURL .replace (e.newURL , '' ); if (popHash === uniqueKey || popHash === `#${uniqueKey} ` || popHash === `/${uniqueKey} ` ) { popStateCallback (uniqueKey); } }); } componentWillUnmount = () => { const { uniqueKey } = this .props ; if (location.hash && location.hash .indexOf (uniqueKey) !== -1 ) { history.go (-1 ); } } render ( ) { return this .props .children ; } } export default Enback ;
这是用法:
1 2 3 4 5 6 7 8 9 10 11 import Enback from '../../enback' ;export default () => ( <Enback uniqueKey = "uniqueKey" popStateCallback = { ()=> {/* here to hide your popup*/} } > <div > This is a popup </div > </Enback > );
不玩 React?没关系,这里有原生的做法:https://github.com/zhaoqize/blog/issues/20
BTW, 副作用其实还是有的。你们猜猜是啥?
At last 谢谢捧场,欢迎 issue 讨论,随手点个 Star 更好 →_→ GitRepo 。