个人博客原文地址:http://www.ltang.me/2018/04/15/jquery-load-back-forward-refresh/
做一个后台管理系统的时候,用到了admin-lte框架。不过其实大部分后台管理系统都是这样的设计,即,左边是可以缩进的菜单栏,右边是内容,用户点击菜单的时候,菜单栏和上边的用户信息栏并不会重新加载,也就是不会跳转到新的页面,紧紧是更新了右边的内容模块。
跟大多数人一样,我使用的是jquery
的load()
方法,如下所示:
<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
的内容,所以,前进、后退、刷新时,可能会退出当前网站、页面,这并不是我们在访问普通网页时期望的前进、后退、刷新行为。
下面提出一种解决方案,实测有效:
...
<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,这里不赘述。