引言
有一些 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。