发布于 

Jquery load 方法下前进、后退、刷新问题的解决

做一个后台管理系统的时候,用到了admin-lte框架。不过其实大部分后台管理系统都是这样的设计,即,左边是可以缩进的菜单栏,右边是内容,用户点击菜单的时候,菜单栏和上边的用户信息栏并不会重新加载,也就是不会跳转到新的页面,仅仅是更新了右边的内容模块。


然而这种实现方式有一种缺陷:当用户点击前进按钮、后退按钮、刷新按钮时,由于实际上用户只访问了一个页面,其他的“功能页面”都是更新此页面中的main-content的内容,所以,前进、后退、刷新时,可能会退出当前网站、页面,这并不是我们在访问普通网页时期望的前进、后退、刷新行为。然而这种实现方式有一种缺陷:当用户点击前进按钮、后退按钮、刷新按钮时,由于实际上用户只访问了一个页面,其他的“功能页面”都是更新此页面中的main-content的内容,所以,前进、后退、刷新时,可能会退出当前网站、页面,这并不是我们在访问普通网页时期望的前进、后退、刷新行为。

跟大多数人一样,我使用的是jqueryload()方法,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<li><a href="javascript:loadMenu('<%=request.getContextPath()%>/commons/redirect.do?path=management/user_list')">用户列表</a></li>

<li><a href="javascript:loadMenu('<%=request.getContextPath()%>/commons/redirect.do?path=management/department_list')"></i>归属部门</a></li>
...
<script>
function loadMenu(path, parameter) {
$('#main-content').load(path, parameter);
}

$(function () {
var defaultPath = '<%=request.getContextPath()%>/commons/redirect.do?path=task/task_list';
loadMenu(defaultPath);
});
</script>

上述的代码中,定义了一个loadMenu方法,按钮点击的时候调用此方法,将新的内容页面加载到main-content这个<div>块中,实现了菜单栏不刷新、内容变化的功能。当第一次进入此页面时,自动调用loadMenu方法,加载默认页面。

然而这种实现方式有一种缺陷:当用户点击前进按钮、后退按钮、刷新按钮时,由于实际上用户只访问了一个页面,其他的“功能页面”都是更新此页面中的main-content的内容,所以,前进、后退、刷新时,可能会退出当前网站、页面,这并不是我们在访问普通网页时期望的前进、后退、刷新行为。

下面提出一种解决方案,实测有效:

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
46
47
48
49
50
...
<script>

$(function () {
$.refresh()
})

function loadMenu(path, parameter) {
$.pushState(path, parameter)
$.loadPage(path, parameter)
}

$.extend(
{
loadPage: function (url, data) {
console.log('loading url: ' + url)
$('#main-content').load(url, data);
},
pushState: function (url, data) {
console.log("pushing state: " + url)
history.pushState({urlStr: url, data: data}, "页面标题", "?_url=" + url);
},

popState: function () {
window.addEventListener("popstate", function () {
var currentState = history.state
if (currentState != null) {
var url = ".." + currentState.urlStr
console.log('poping state: ' + url)
$.loadPage(url, currentState.data)
}
})
},

refresh: function () {
var currentState = history.state;
if (currentState != null) {
var loadUrl = ".." + currentState.urlStr
console.log('refreshing state: ' + loadUrl)
$.loadPage(loadUrl, currentState.date)
}else{
var defaultPath = '<%=request.getContextPath()%>/commons/redirect.do?path=task/task_list';
loadMenu(defaultPath)
}
}
}
)

$.popState()
</script>

如上述代码,我们拓展了popState/refresh方法,当用户点击前进(后退)、刷新按钮时会分别触发这两个方法, 然后在方法中获取到用户(这里指我…)期望的路径,通过load方法将这些内容加载。

那么这些“记录”是如何保存和获取的呢?当用户点击菜单(按钮),调用loadMenu方法时,我们先调用pushState方法,将他要访问的页面添加到历史记录history.pushState,然后在前进、后退、刷新时获取到对应的历史记录history.state,通过load方法加载这些内容饥渴。并且参数也可以通过对应data字段保存和获取。

实测有效,不过还需要考虑,加载页面后菜单栏的active问题。可以通过传递的参数来判断,修改className,这里不赘述。