页面历史记录管理,其实和浏览器自带的前进和后退按钮很类似,就是为了保证在某个页面点击返回键的时候,能够正确地返回用户想要回到的上一个页面。对于浏览器来说,如果我们依次打开页面A-->B-->C-->D,我们在D页面点浏览器的回退是回到C页面,C回到B,B回到A。但是对于一个业务系统来说,这种返回逻辑太简单了,不能满足一些特点场景的使用。
比如我们的混合app主页是A(任务列表页面,一条一条的任务),我们点击列表的某一条数据后,会跳转到B(router页面,用户不可见),B页面会根据一些条件跳转到C或者D等页面。如果用户在C页面点返回,显然希望回到的是A页面,而不是B页面。我们的项目是这样的:定义open()和back()函数,open用来打开新页面,back用来从当前页面返回。
function open(url, parameter, config)
{
}
function back()
{
}
back函数不需要任何参数,而open参数必需要传页面的url。页面点返回的时候会调用back(),而打开页面调用的是open(url)。既然要打开一个新页面,当然你要告诉我页面地址,不然怎么知道打开哪儿一个页面呢。而返回的时候,显然不需要任何参数。当然如果你的返回逻辑十分诡异,那么这就不是back()的概念了,而是open()。
我做的历史记录其实就是:在open()不同页面的时候,记录一些配置信息,然后根据这些配置信息来决定:从当前页面返回的时候,到底应该回到哪一个页面。我在项目中实现的配置信息就2个:isHomePage和needRecordHistory。
/**
* 打开页面
*
* @param url: 页面url地址(可以唯一标识一个页面)
* @param parameters: 需要传递给页面的参数
* @param config: 配置信息{isHomePage:true, needRecordHistory:true}
*
* isHomePage: true代表需要打开的页面是首页,在首页点返回我们希望回到android桌面;
* needRecordHistory: 是否需要加入到历史记录之中.
*
* 考虑这种情况: A跳转到B,B可以跳转到C,也可以跳转到D.
* B其实只是一个router页面, 仅仅中转而已,是用户不可见的.
* 我们在C页面返回, 自然希望回到A, 而不是B, 也就是说B页面不需要记录到历史记录当中.
*
* 我们假设当前页面currentPage=A, 那我们在A页面可以写这样的代码打开B页面: A->B
* open("B",{},{needRecordHistory:true}); 这意味着在B页面点返回,能够回到A页面;
*
* 在B页面可以通过下面的代码打开C页面:B->C
* open("C",{},{needRecordHistory:false}); 当前页面是B,打开页面C的时候,当前页面B不需要记录历史记录.
* 这样我们在C页面点返回键,会回到A
*
*/
function open(url, parameter, config)
{
parameter = $.extend({}, parameter);
config = $.extend({},default_options, config);
// 创建新页面
var target_page = buildMobilePage({url:url, parameter:parameter});
if(!currentPage || config.isHomePage)
{
clear();
// 忽略config,忽略parameter,因为从主页返回android桌面,不需要什么参数
record_page_back_relation(url, true, HOME_PAGE, {});
}
else
{
record_page_back_relation(url, config.needRecordHistory, currentPage.url, currentPage.parameter);
}
// 改变当前页面
currentPage = target_page;
// 显示当前页面
currentPage.show();
}
/**
* 假如依次新打开4个页面,A->B->C->D(A是我们的主页, A打开B, B打开C, C打开D).
* 那么在D页面点返回键回到C, C页面回到B, B页面回到A, A页面是主页无返回键.
* 接下来页面之间跳转无非以下3种情况:
* 1.C->E或A->F, 这个时候需要新增一条父子关系,记录是C页面打开了E页面.
*
* 2.A->C,这个时候需要更新下父子关系,以前是B打开了C页面,C页面返回到B;现在是A打开了C页面,C页面需要返回到A.
*
* 3.D->A或D->C, 啥也不需要做,只是页面返回而已,实际上页面之间的父子关系并没有发生变化.比如我们从D页面跳到B页面,
* 在B页面点返回的时候,我们还是希望回到A页面,而不是D页面.
*
* @param target_url 需要打开的目标页面的url
*
* @param needRecordHistory 当前页面 -> target_url是否需要加入历史记录.
* 即在target_url页面点返回,是回到当前页面,还是回到当前页面的父页面.
*
* @param back_url target_url页面的上一个页面,其实就是currentPage的url
* @param back_parameter target_url的上一个页面需要的参数,其实就是currentPage的parameter
*
*/
function record_page_back_relation(target_url, needRecordHistory, back_url, back_parameter)
{
// 当前页面要求打开当前页面的情况,不需要记录历史记录.
if(target_url == back_url)
{
return;
}
var parent_config = {"needRecordHistory":needRecordHistory, "back_parameter":back_parameter, "back_url":back_url};
var situation = which_case_belongto(target_url, back_url);
if(situation == "case1")
{
bac