我正在努力实现history.js a jQuery plugin对于 IE 8 和 9。该演示在 IE10+ 和其他现代浏览器中似乎没问题,但我无法理解 IE <= 9 的以下问题。该演示是一个 asp.net mvc5 应用程序,我想提供单页用户体验,我只是加载部分 View 并通过 ajax 执行后操作。所有 View 都加载在我的主视图中的 #shell
div 中。也许我错过了一些东西!!
我的演示应用程序以 http://localhost:1089/
开头,这是呈现登录页面的第一个请求。任何其他 pushState() 都会导致 url 发生变化并附加 #Home/About?ref=one
。
以下是我在layout.cshtml中执行的脚本,该脚本仅加载一次:
(function (window, undefined) {
History.Adapter.bind(window, 'statechange', function () {
var state = History.getState();
if (state.data.options == undefined) {
alert("options is undefined");
var options = {
url: state.url,
type: "GET",
dataType: "html"
};
GetPartial(options);
} else {
GetPartial(state.data.options);
}
});
})(window);
$(document).on('click', 'a', function (e) {
e.preventDefault();
var options = {
url: $(this).prop('href'),
type: "GET",
dataType: "html"
};
History.pushState({ options: options }, $(this).text(), $(this).prop('href'));
});
function GetPartial(options) {
if (options) {
$.ajax({
url: options.url,
type: options.type || 'GET',
dataType: options.datatype || 'html',
async: true,
data: options.dataToPost,
beforeSend: function() {
$("#loaderMain").show();
},
complete: function() {
$("#loaderMain").hide();
},
cache: false,
}).success(function(response, status, xhr) {
var ct = xhr.getResponseHeader("content-type") || "";
if (ct.indexOf('html') > -1) {
// returned result is of type html, so act accordingly
if (options.selector == undefined) {
InjectContentToShell(response);
} else {
$(options.selector).empty().append(response);
}
} else if (ct.indexOf('json') > -1) {
// returned result is of type json, so act accordingly
}
}).fail(function(e) {
console.log(e);
});
}
}
function InjectContentToShell(content) {
$('#shell').fadeOut(100, function () {
$(this).empty().append(content);
}).fadeIn(100);
}
当我渲染第一页时,我通过 pushState 方法向历史记录添加一个条目,如下所示:
$('#submit').on('click', function (e) {
e.preventDefault();
var formInstance = $(this).closest('form'),
dataToPost = formInstance.serialize();
var options = {
url: formInstance.prop('action'),
type: formInstance.prop('method'),
dataType: "html",
dataToPost: dataToPost
};
History.pushState({ options: options }, "Home - All Summary Views", "/Home/Index");
});
推送上面的状态,在 html4 浏览器中将 url 更改为 http://localhost:1089/#Home/Index
就可以了。我能够前进和后退。这效果很好。
现在,当我在 html4 浏览器中刷新页面时,发送到服务器的请求是第一个 url,即 http://localhost:1089/
,它将第一个 View 带到客户端。因此,用户可以看到第一页,即登录屏幕。然后 statechange
事件被触发,状态 url 仍然会记住刷新页面的最后一个 url,并向服务器发出对此 url 的新请求。然后将响应注入(inject) shell 中。
所以,问题是 - 在页面刷新时,用户立即获得两个 View - 用户开始浏览 session 的初始页面,很快第二个页面从服务器加载并通过动画添加到 shell,就像状态更改时一样事件被触发,History.getState()
仍然记住最后一个 url。
我不想在页面刷新时显示此初始页面。如果这个问题得到解决,那么我认为这个 History.js 一切正常!
我的演示应用程序在 html5 浏览器中运行良好,因为在每个 History.pushState()
上,浏览器的 url 都会更改为我指定的 url。当页面刷新时,请求将根据该 url 发送到服务器,而不是从浏览 session 中的第一个 url 开始。
最佳答案
在尝试了很多方法之后,我提出了以下解决方案,以避免向使用 html4 浏览器的用户显示第一个 View ,即登录页面:
我创建了一个 View “Index”,它是第一个渲染的 View 。其中没有任何 html 内容,但有以下脚本:
<script>
$(function () {
if (History.getCurrentIndex() == 0) {
var options = {
url: "/Account/Login",
type: "GET",
dataType: "html"
};
History.pushState({ options: options }, "Login Page", "/Account/Login");
}
});
</script>
上面的代码检查当前索引是否为 0。如果为 0,则意味着用户刚刚开始浏览历史记录,并且应该显示登录屏幕。如果它不为 0,则意味着用户处于应用程序内用户旅程的某个其他步骤,但不执行任何操作。一旦呈现此 View ,就会触发 statechange
事件,该事件已经具有有关用户请求刷新的页面 url 的信息。根据我的问题中上面的 statechange 事件处理程序的逻辑,从服务器请求该资源并将其注入(inject)到 #shell
容器中。
上述解决方案运行良好,为用户提供了与使用 html5 浏览器相同的体验。上面的代码适用于我,但我很高兴知道是否有人有任何其他解决方案。
关于javascript - 当使用 History.js 从应用程序中的其他位置刷新页面时,如何避免渲染浏览 session 的初始 View ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21910467/