蓝光是指以 app 交互的方式呈现搜索结果页。神马已经有Nba, 视频, 明星, 旅游等行业领域有蓝光效果。大家可以在 神马搜索 上搜搜各种关键词来触发,比如 nba
, 杭州
, 周杰伦
等。
图1 蓝光效果图
这次我接到的任务是旅游蓝光第三版的改版。
图2 旅游目的地第三版
这次第三版和第二版重要的一个区别是增加了模态浮层的交互。第二版是以feed流的形式一直往下加载直到加载完毕,第三版需要弹出一个可滑动的浮层,有一些手势的操作,这种交互在app上很常见,但是在web app上市场上还没出现。交互效果如下图所示(query: 北京):
图3 旅游目的地浮层
这种浮层在神马一般做法是使用 中间页
的方式,一般会改变他的hash来触发一些事件插入中间页html。本来想在滑动到顶端将 结果页 隐藏,让页面正常布局而实现内部滚动,但是在实验的时候上述转变的那一瞬间因为滚动条的改变页面重排会有明显的闪屏,所以放弃这种方式,内部滑动使用js来模拟,用了正祥神马七绝的竖向滑动组件。
实现这种滑动交互定位是个问题。本来想的是中间页用fix的方式来坐容器,里面内容translate3d的方式来移动,但是测试在华为这种安卓手机下内容会一块一块加载出来而不是全部加载,所以最后的方案是:
1.正常relative布局,点击展开时将页面定位到当前视口的下方,计算公式如下;
bodyHeight - windowHeight - scrollTop
2.当中间页渲染完毕后,进入到中间状态,中间状态计算的位置如下:
curViewBottomY + windowHeight - MARGIN_TOP;
其中,curViewBottomY就是上一步计算的当前视口的下方
3.到达中间页时,绑定滑动事件。此时,还有几个状态:
fullPage
阶段,即固定位置、绑定垂直滑动组件、绑定下拉关闭事件等。 因为安卓下的bug,要滑动时
此浮层在内部还是有切换,如图所示:
图4 内部频道切换
这种涉及到两个问题
首先,由于中间页的数据结构和结果页某些相似,所以这些数据可以由php传给我们,但是有些数据结构又不一样,所以得两种方式都支持。我在进行ajax请求时又加了一层catch,这样家再过的数据直接从内存中返回,不必再进行一次请求,虽然浏览器端有缓存,但再发一次304请求在移动端还是开销比较大。
页面之间切换我们可以将之抽象出来,所有页面都会有共同的特性:
我将头部、尾部、内容分离开。头部主要是部可能是一些tag列表、酒店。美食的展示区域。尾部主要是一些筛选等html,这些相对于页面是固定的,信息流列表就是可滑动加载的区域,这一块得使用滑动组件。为了避免过多事件而造成内存泄露,在切换的时候进行解绑。附加数据是数据传入模板的一些额外的数据,比如打点信息、城市名称等等。
事件将其使用立即函数来封装,返回一个对象,其有两个属性 bind
和 unbind
,其中绑定的函数不能使用匿名函数,因为需要解绑找到对应的函数,因为使用立即函数,这些函数都是私有的,不可见的。
z-index的管理是现在还是没有头绪,有时需求a盖住b,有时b盖住a,现在做法是特殊需求在外层加一个class改变其z-index,但这种做法着实恶心。
该页面复杂,需要依赖的js很多,怎么让这些不同功能的js直接来通信?我使用自定义事件的方式来解耦,比如浮层开始要滑动有时间,到达fullpage是有事件,关闭时也有事件来通知浮层内容页解绑。为了达到更好的体验,如下拉时有一个提示来判断用户是否想关闭页面,如图:
我也是在正祥滑动组件里trigger一些事件来提醒我们中间页做一些操作。因为滑动会触发很多次,我们使用封装的一个throttleFn函数来执行,提高效率。
由于ios版uc以前计算地址栏有问题,就是将地址栏算入页面的高度,直到10.7.5才修复,所以对之前的版本进行了一些hack兼容,很恶心,还好ios用户升级快,打算在后面迭代时候删除此hack。
当用户在浮层滑到中间状态时刷新,页面重新加载后布局就会乱,因为在刷新的时候页面刚进来滚动条的高度是0,在等大多结构下载完才将高度恢复过来,但我的浮层位置是基于滚动条算的,所以布局有问题,但也不能看到滚动条为0就不弹出浮层或去掉hash,因为现在手机屏幕很大,弹出浮层的入口按钮很可能出现在第一屏幕,那样用户就永远打不开浮层了。我的做法是进入浮层后将当前滚动条的位置往localstorage里,刷新的时候如果滚动条为0将其就读取localstorage里存的值,还得再判断一下用户是否是刷新,就需要在 onunload
事件触发的时候往localstorage存入一个标示变量,当有这个标示变量为true是才从localstorage里读取滚动条的高度。页面加载出来过几百毫秒将这个值重新至为false。
可优化的点还有很多,比如之前是单个sc模块写的,所有js内敛到一个js,导致该js也是很庞大。现在在开景点蓝光,做成了行业的形式,这样将js分离开来,前端可以更好的做缓存,从目的地往景点跳也会更快,后期把目的地迁移到旅游第三版行业文件夹里。app能实现的,我们web app端也能实现!