javascript - 当使用 History.js 从应用程序中的其他位置刷新页面时,如何避免渲染浏览 session 的初始 View ?

标签 javascript jquery asp.net-mvc history.js

我正在努力实现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 一切正常!

The above problem is also mentioned as a concept of bookmarking in the this article. Refer to the first figure and the text written above it.

我的演示应用程序在 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/

相关文章:

javascript - 如何使用 jQuery 或 Javascript 返回根 HTML 标签

javascript - jquery 无法读取文本字段值

c# - 使用 SimpleMembership (MySQL) 将用户添加到角色时出现外键问题

jquery - 如何在 ASP.NET MVC 应用程序中管理单个 JavaScript 文件?

javascript - 如何对 es6 模块进行功能检测

javascript - 箭头函数进入react组件中的 "ordinary"函数表达式

javascript - 使用 javascript/jquery 进行复选框操作

javascript - jQuery 错误??如何获取所有可见行中的第一个 "td"

javascript - 我现在在鼠标悬停时显示一个元素,我想在鼠标移出后隐藏它。我该怎么做呢?

javascript - ASP.NET MVC 3 和 Google map API