单页面返回上一页,如何保持数据?
先讲一下背景:用户从列表页进入详情页,然后用户返回列表页,列表页需要停留在上次离开时的页面状态(页面滚动高度、搜索条件等等)。
最近在做车问项目,用户需要频繁往返列表页和详情页,为了提升用户体验,我将页面系统改成了单页面。虽然性能提升上去了,但是产品经理反馈列表页面体验并不好,需要解决页面返回保持页面状态。
以前做项目,大部分都是页面直接<a href="xxx"/>
跳转,这时候浏览器会将上一个页面的状态保存起来,用户返回的时候就会自动恢复。现在单页面需要模拟回这个功能,于是就有了下面的思路。
思路
用户即将离开页面 -> 保存Vue.$data和当前页面滚动高度到sessionStorage
用户从详情页返回列表页 -> 从sessionStorage读取之前保存的数据 -> 页面重新设置
代码
/**
* 页面状态持久化
*
* @author 张子超
* @since 2018-08-16
*/
import $ from "jquery";
var PageState = {};
var defaultUIData = ()=>{
return {
scrollTop: $(window).scrollTop()
};
}
/**
* 启动监听,当Component.keepAlive = true时启用
* @param {*} $root App对象
*/
PageState.start = function($root){
var timer;
window.addEventListener("scroll",()=>{
//延时保存
clearTimeout(timer);
timer = setTimeout(()=>{
//获取当前的组件
var component = $root.$route.matched["0"].components.default;
if(component.keepAlive){
//保存当前组件的数据
PageState.save($root.$root.$children["0"].$children["0"]);
}
}, 300);
});
}
/**
* 保存当前组件的数据
* @param {*} vueObj
*/
PageState.save = function(vueObj){
var key = 'PS:'+location.pathname+location.search;
var state = {
//页面数据
PageData: vueObj.$data,
//UI数据
UIData: defaultUIData()
};
try{
sessionStorage.setItem(key, JSON.stringify(state));
}catch(e){
console.error(e);
}
}
PageState.recover = function(vueObj, initCb = ()=>{}, recoverCb = ()=>{}){
var key = 'PS:'+location.pathname+location.search;
try{
var dataStr = sessionStorage.getItem(key);
if(!dataStr){
console.log('无法获取恢复数据');
initCb();
return;
}
console.log('恢复数据');
var state = JSON.parse(dataStr);
console.log(state);
for(var i in state.PageData){
console.log('恢复:'+i+'='+state.PageData[i]);
vueObj[i] = state.PageData[i];
}
var scrollTop = state.UIData.scrollTop;
if(scrollTop){
setTimeout(()=>{
console.log('滚动:'+scrollTop);
$(window).scrollTop(scrollTop);
}, 10);
}
//清除状态
PageState.clear();
//回调恢复完成
recoverCb();
}catch(e){
console.error(e);
//回调恢复完成
initCb();
}
}
PageState.clear = function(){
sessionStorage.clear();
}
export default PageState;