4

我看到 Lifehacker 能够在使用 AJAX 更新部分页面时更改 url。我猜这可以使用 HTML5 或 history.js 插件来实现,但我猜 lifehacker 两者都没有使用。

有没有人知道他们是如何做到的?我是 AJAX 新手,只是设法使用 Ajax 更新了部分页面。


感谢@Robin Anderson 提供详细的分步算法。我试过了,它工作正常。但是,在我可以在生产中测试它之前,我想由你运行我拥有的代码。我做对了吗?

<script type="text/javascript">  
var httpRequest;  
var globalurl;
    function makeRequest(url) {  
    globalurl = url;
    /* my custom script that retrieves original page without formatting (just data, no templates) */
    finalurl = '/content.php?fname=' + url ;

    if(window.XMLHttpRequest){httpRequest=new XMLHttpRequest}else if(window.ActiveXObject){try{httpRequest=new ActiveXObject("Msxml2.XMLHTTP")}catch(e){try{httpRequest=new ActiveXObject("Microsoft.XMLHTTP")}catch(e){}}}  

    /* if no html5 support, just load the page without ajax*/
    if (!(httpRequest && window.history && window.history.pushState)) {     
            document.href = url;
            return false;  
    } 

    httpRequest.onreadystatechange = alertContents;  
    alert(finalurl);    /* to make sure, content is being retrieved from ajax */
    httpRequest.open('GET', finalurl);  
    httpRequest.send();  
    } 

    /* for support to back button and forward button in browser */
    window.onpopstate = function(event) {
            if (event.state !== null) {
                    document.getElementById("ajright").innerHTML = event.state.data;
            } else {
                    document.location.href = globalurl;
                    return false;
            };
    };    

    /* display content in div */
    function alertContents() {  
            if (httpRequest.readyState === 4) {  
            if (httpRequest.status === 200) {  
                    var stateObj = { data: httpRequest.responseText};
                    history.pushState(stateObj, "", globalurl);     
                    document.getElementById("ajright").innerHTML = httpRequest.responseText;
            } else {  
                    alert('There was a problem with the request.');  
            }  
            }  
    }  
    </script> 

PS:我不知道如何在评论中粘贴代码,所以我在这里添加了它。

4

2 回答 2

8

为了在浏览器中使用历史 API,不需要将标记设为 HTML5,即使它是 HTML5 功能。

使用 AJAX 加载所有页面转换的一种非常快速且简单的实现是:

  1. 将除 rel="external" 存在于函数“ChangePage”之外的所有链接连接起来
  2. 当 ChangePage 被触发时,检查浏览器是否支持 history API。
  3. 如果不支持历史 API,请推送主题标签或将正常的整页加载作为后备。
  4. 如果支持历史 API:
    1. 防止正常的链接行为。
    2. 将新 URL 推送到浏览器历史记录。
    3. 向新 URL 发出 AJAX 请求并获取其内容。
    4. 在响应中查找您的内容 div(或类似元素),从中获取 HTML,并将当前页面上相应元素的 HTML 替换为新的。

这将很容易实现,易于管理缓存并与谷歌的机器人一起工作,缺点是不是“优化”的,当你改变时它会在响应上产生一些开销(与更复杂的解决方案相比)页。

还将具有向后兼容性,因此旧浏览器或“非 javascript 访问者”只会获得正常的页面加载。

关于该主题的有趣链接

编辑:

值得一提的另一件事是,您不应该将它与 ASP .Net Web Forms 应用程序一起使用,这可能会搞砸回发处理。

代码补充:

我整理了这个功能的一个小演示,你可以在这里找到

它只使用 HTML、Javascript (jQuery) 和一点点 CSS,我可能会建议您在使用之前对其进行测试。但我已经在 Chrome 中检查了一些,它似乎工作得很好。

我推荐的一些测试是:

  • 在优秀的浏览器 Chrome 和 Firefox 中进行测试。
  • 在 IE7 等旧版浏览器中进行测试
  • 在不启用 Javascript 的情况下进行测试(只需安装 Noscript 或类似于 Chrome/Firefox)

这是我用来实现此目的的 javascript,您可以在上面的演示中找到完整的源代码。

/*
    The arguments are:          
        url: The url to pull new content from
        doPushState: If a new state should be pushed to the browser, true on links and false on normal state changes such as forward and back.
*/
function changePage(url, doPushState, defaultEvent)
{
    if (!history.pushState) { //Compatability check
        return true; //pushState isn't supported, fallback to normal page load
    }

    if (defaultEvent != null) { 
        defaultEvent.preventDefault(); //Someone passed in a default event, stop it from executing
    }

    if (doPushState) {  //If we are supposed to push the state or not
        var stateObj = { type: "custom" }; 
        history.pushState(stateObj, "Title", url); //Push the new state to the browser
    }               

    //Make a GET request to the url which was passed in
    $.get(url, function(response) {             
        var newContent = $(response).find(".content");      //Find the content section of the response
        var contentWrapper = $("#content-wrapper");         //Find the content-wrapper where we are supposed to change the content.
        var oldContent = contentWrapper.find(".content");   //Find the old content which we should replace.

        oldContent.fadeOut(300, function() { //Make a pretty fade out of the old content
            oldContent.remove(); //Remove it once it is done
            contentWrapper.append(newContent.hide()); //Add our new content, hidden
            newContent.fadeIn(300); //Fade it in!
        });

    });
}


//We hook up our events in here
$(function() {
    $(".generated").html(new Date().getTime()); //This is just to present that it's actually working.

    //Bind all links to use our changePage function except rel="external"
    $("a[rel!='external']").live("click", function (e) { 
        changePage($(this).attr("href"), true, e);
    });

    //Bind "popstate", it is the browsers back and forward
    window.onpopstate = function (e) { 
        if (e.state != null) {
            changePage(document.location, false, null); 
        }
    }
}); 
于 2011-11-20T16:48:35.197 回答
0

DOCTYPE 对页面可以使用哪些功能没有影响。

他们可能直接使用 HTML5 History API。

于 2011-11-20T16:25:48.670 回答