防止在Chrome和IE中点击后退按钮时重新加载Ajax数据

7
我目前正在开发一个网站,主页上显示最新的10篇博客文章。当我向下滚动并且快到屏幕上最后一个项目时,会自动加载另外10篇博客文章,以此类推(这就是无限滚动的功能)。
如果用户单击任何博客条目,则会跳转到另一页以显示有关该博客条目的详细信息。当用户单击返回按钮时,将返回显示条目的主页。
请注意,主页使用Ajax加载数据。
假设以下场景:
1. 用户进入网站,并加载了1到10个条目(通过Ajax)。 2. 用户向下滚动,接下来的10个条目,即第11到20个条目,也通过Ajax加载。请注意,页面现在显示了1到20个条目。 3. 用户继续向下滚动,现在加载了21到30个条目,总共显示了1到30个博客条目。 4. 用户单击25号条目,将显示25号条目的页面。 5. 用户单击返回按钮,所有1到30个条目都将显示出来。
现在,如果用户使用FireFox,Opera或Safari,并执行步骤5(即单击返回按钮返回主页),则博客条目将仅在屏幕上显示,而不重新加载。然而,在IE和Chrome中,当用户单击返回按钮时,页面会重新加载,只会显示1到10项。
我不喜欢IE和Chrome的行为。用户应该看到1到30项。如何确保所有浏览器都像FireFox一样?
谢谢。
更新:
这是我正在使用的代码
首先,这是我的html
<html>
    <body>

        <section id="content">
            <section id="articles">
                <!-- This section is filled by jQuery/Ajax -->
            </section>

            <section id="loading-spinner">
                <img src="ajax-loader.gif" />
            </section>

        </section>

    </body>
</html>

这是我的jQuery代码

/**
 * 
 * This file uses a bunch of programming concepts, but the most important one is ensuring ajax calls run as a critical section
 * ... (this means if ajax is already called, then another instance of JavaScript cannot get into the critical section)
 * 
 * .. For more details, please read: https://dev59.com/133aa4cB1Zd3GeqPZSmh
 * 
 */


load_more_posts = function () {

    // If we almost reach the bottom of the document, then load more posts
    if ( jQuery(window).scrollTop() >= jQuery(document).height() - jQuery(window).height() - 300) {

        // If the value of the promise is not pending, then we can call the load_posts function (the load_posts function will change the status to pending when it is executing the ajax request)
        if (ajax_status.state() !== "pending") {
            load_posts();

        }
    }
};


function load_posts() {

    ajax_status = jQuery.ajax({

        type:       'post',

        dataType:   'json',

        beforeSend: function(xhr) {

            if(jQuery.data(document.body, 'load_page') == false) {
                xhr.abort();
            }

            else {
                // Show the spinner
                jQuery('#loading-spinner').visible();
            }



        },

        url:        '../link/to/get_poasts.php',

        data:       {
            action:             'load_posts',

            js_query_data:      query_data,
            js_page:        jQuery.data(document.body, 'page_to_load')

        },

        success:    function (response) {

            if (response.isSuccessful) {

                var number_of_post_items = response.posts_array.length;

                for (var i = 0; i < number_of_post_items; i++) {

                    // If the item is already returned from the database and posted. then we skip it, otherwise, keep insert a new record 
                    if (jQuery('#articles').find('#article-' + response.posts_array[i].post_id).length == 0) {

                        // Add 'article'
                        jQuery('#articles').append('<article id="article-' + response.posts_array[i].post_id + '"></article>');

                        // More code here to add details about each article, such as title, excerpt...etc.


                    }
                }




                // Increase the value of the page to load by 1, and save it.
                page = jQuery.data(document.body, "page_to_load");
                page = page + 1;
                jQuery.data(document.body, "page_to_load", page);



                jQuery(window).on('scroll', load_more_posts);

            }

            else {
                // Display error message
                jQuery('#articles').append('<div>' + response.message + '</div>');

                // Make sure no further AJAX requests are made
                jQuery.data(document.body, 'load_page', false);
            }

        }
    }).always(function() {

        // Hide the spinner
        jQuery('#loading-spinner').invisible();
    });

    return ajax_status;
}



// Create a new promise. This will be used to ensure that no two calls hit the critical section at the same time
// ... (the critical section in this case is the time when we retrieve data from the database. We only want one call at a time)

var ajax_status = new jQuery.Deferred();


jQuery(document).ready(function() {

    // Hide the loading spinner first
    jQuery('#loading-spinner').invisible();


    // We resolve the promise, making sure it is ready (this is an intial state)
    ajax_status.resolve();

    // Initial values that are used
    jQuery.data(document.body, 'page_to_load', 1);

    // This parameter is used to stop loading pages when no more items are available to be displayed 
    jQuery.data(document.body, 'load_page', true);



    // Initial loading of poasts
    load_posts();



    // Enable on scrolling to load more pasts (to allow infinite scrolling)
    jQuery(window).on('scroll', load_more_posts);


});

你有一堵以“IE和Chrome做某些其他浏览器不做的事情”结尾的长篇文字:现在是时候将你的问题简化为jsfiddle.net或jsbin.com的示例了。你能在那里重现它吗?很好,我们可以帮助你。否则,你的问题可能不在你认为的地方,在寻求我们的帮助之前,你应该先找出问题所在。 - Mike 'Pomax' Kamermans
1
这取决于您如何加载页面。您可以尝试将所有ajax请求保存到“localStorage”中,然后在页面加载时,您可以从localStorage中加载所有结果(0到30),而不是进行新的ajax调用。 - jasonscript
@Mike'Pomax'Kamermans:我按照你的建议添加了代码。希望这有所帮助。 - Greeso
@jasonscript:我尝试使用sessionStorage代替localStorage,但是我遇到了一个不同的问题。我遇到的问题是当我想要刷新页面时,它仍然加载会话数据而不是要重新加载的实际数据。这是因为这两个浏览器不能区分后退按钮和页面刷新。对于IE和Chrome来说,它们都是相同的,不幸的是。 - Greeso
1
考虑使用HTML5历史记录API。这将允许您将“pushState(data)”推送到堆栈上,当用户点击后退时会弹出。您推送的数据将是列表项。在该页面上覆盖“onpopstate”以检查“data”。请注意,它并不适用于所有浏览器版本:http://caniuse.com/#search=history - jmathew
2个回答

0

让大家知道,这是我想出来的在所有浏览器中都一致的解决方案。不幸的是,这个解决方案需要一个重新加载/刷新按钮来重新加载数据。我试图避免这种情况,但无法做到。在IE和Chrome解决bfcache问题之前,我将坚持使用这个解决方案。

首先,这是新的HTML代码

<html>
    <body>

        <section id="content">

            <a id="refresh">
                <img src="link/to/refresh.png" title="Refresh" alt="refresh" />
            </a>

            <section id="articles">
                <!-- This section is filled by jQuery/Ajax -->
            </section>

            <section id="loading-spinner">
                <img src="ajax-loader.gif" />
            </section>

        </section>

    </body>
</html>

这是 JavaScript 代码

/**
 * 
 * This file uses a bunch of programming concepts, but the most important one is ensuring ajax calls run as a critical section
 * ... (this means if ajax is already called, then another instance of JavaScript cannot get into the critical section)
 * 
 * .. For more details, please read: https://dev59.com/133aa4cB1Zd3GeqPZSmh
 * 
 */


load_more_posts = function () {

    // If we almost reach the bottom of the document, then load more posts
    if ( jQuery(window).scrollTop() >= jQuery(document).height() - jQuery(window).height() - 300) {

        // If the value of the promise is not pending, then we can call the load_posts function (the load_posts function will change the status to pending when it is executing the ajax request)
        if (ajax_status.state() !== "pending") {
            load_posts();

        }
    }
};


function load_posts() {

    ajax_status = jQuery.ajax({

        type:       'post',

        dataType:   'json',

        beforeSend: function(xhr) {

            if(jQuery.data(document.body, 'load_page') == false) {
                xhr.abort();
            }

            else {
                // Show the spinner
                jQuery('#loading-spinner').visible();
            }



        },

        url:        '../link/to/get_poasts.php',

        data:       {
            action:             'load_posts',

            js_query_data:      query_data,
            js_page:            sessionStorage.getItem("page_to_load")

        },

        success:    function (response) {

            if (response.isSuccessful) {

                var number_of_post_items = response.posts_array.length;

                for (var i = 0; i < number_of_post_items; i++) {

                    // If the item is already returned from the database and posted. then we skip it, otherwise, keep insert a new record 
                    if (jQuery('#articles').find('#article-' + response.posts_array[i].post_id).length == 0) {

                        // Add 'article'
                        jQuery('#articles').append('<article id="article-' + response.posts_array[i].post_id + '"></article>');

                        // More code here to add details about each article, such as title, excerpt...etc.

                        var history_session = get_history_session_name();
                        var history = sessionStorage.getItem(history_session);
                        var article_content = jQuery('#articles').find('#aarticle-' + response.posts_array[i].post_id)[0].outerHTML;

                        sessionStorage.setItem(history_session, history + article_content);

                    }
                }




                // Increase the value of the page to load by 1, and save it.
                page = parseInt(sessionStorage.getItem("page_to_load"));
                page = page + 1;
                sessionStorage.setItem("page_to_load", page);


                jQuery(window).on('scroll', load_more_posts);

            }

            else {
                // Display error message
                jQuery('#articles').append('<div>' + response.message + '</div>');

                // Make sure no further AJAX requests are made
                jQuery.data(document.body, 'load_page', false);
            }

        }
    }).always(function() {

        // Hide the spinner
        jQuery('#loading-spinner').invisible();
    });

    return ajax_status;
}




function get_history_session_name () {
    session_name = 'history___' + escape(location.href);
    return session_name;
}




// Create a new promise. This will be used to ensure that no two calls hit the critical section at the same time
// ... (the critical section in this case is the time when we retrieve data from the database. We only want one call at a time)

var ajax_status = new jQuery.Deferred();


jQuery(document).ready(function() {

    // Hide the loading spinner first
    jQuery('#loading-spinner').invisible();


    // We resolve the promise, making sure it is ready (this is an intial state)
    ajax_status.resolve();

    // This parameter is used to stop loading pages when no more items are available to be displayed 
    jQuery.data(document.body, 'load_page', true);


    // Get the name of the history session
    var history_session = get_history_session_name();

    if (sessionStorage.getItem(history_session) === null) {

        // Set the history session storage
        sessionStorage.setItem(history_session, "");


        // Initial values that are used
        sessionStorage.setItem("page_to_load", 1);

        // Load the posts
        load_posts();

    }


    // Load from history when the back button is clicked
    else {
        jQuery('#articles').append(sessionStorage.getItem(history_session));
    }



    // Enable on scrolling to load more pasts (to allow infinite scrolling)
    jQuery(window).on('scroll', load_more_posts);


    // Reload data when the refresh button is clicked
    // ... We are using a refresh button because if we go to a page that already had history, ...
    // ... and even though we went to that page without using the back button (i.e, via links or directly via the url), ...
    // ... then the history session will be displayed. ...
    // ... Therefore a reload button is needed to overcome this problem if you like to reload data
    jQuery("#refresh").click(function () {

        // Reset/clear the articles section first
        jQuery('#articles').html("");

        // reset the 'load_page' variable
        jQuery.data(document.body, 'load_page', true);


        // Reset/clear the history session storage
        sessionStorage.setItem(history_session, "");

        // Start with loading page 1
        sessionStorage.setItem("page_to_load", 1);

        // Load the posts
        load_posts();
    });

});

希望这能有所帮助。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接