如何在URL中显示Ajax请求?

31
我想要的是能够改变页面某个部分并具有动态URL链接的功能,其中我可以指定变量,例如#calendar=10_2010tabview=tab2
请查看以下示例:点击此处查看精确演示 所以这是我需要的链接格式:#calendar=10_2010&tabview=tab2
链接中需要包含变量,如calendartabview,以便我可以在不刷新页面的情况下更改单个页面上的多个内容。
或者类似于http://www.wbhomes.com.au这样的另一种格式,这正是我想要的,但第一种格式也很好,只是这样更加美观。 要求: - 需要可以从任何地方访问,例如电子邮件,或者在url栏中输入。 - 链接应该出现在历史记录中,因此如果我按下后退或前进按钮,页面就需要被访问。 - 页面刷新也需要工作。
一些资源:
示例:www.developer.yahoo.com/
  • www.facebook.com - 你个人资料页面侧边栏的链接

  • www.wbhomes.com.au/ - 我需要的东西基本一致

  • www.flickr.com/

  • www.youtube.com

  • 一些教程:


    请帮帮我!我从未找到任何解决方法,但我不想使用 jQuery、API 或任何库,我想拥有一个可工作的 Javascript/AJAX 和 PHP 脚本。


    我不太明白你的意思。AJAX在你所描述的内容中起什么作用?#符号是指页面上的一个锚点。我认为那不是你想要的。你很可能想要一个查询字符串,然后在服务器端处理它。你可以在客户端处理它,在这种情况下,你需要解析URL的查询字符串并获取其中的值。 - DA.
    3
    他在谈论Facebook所做的那种事情,将AJAX请求的路径放入哈希中。 - Matchu
    Ajax在我点击链接时更改内容时出现,这部分是有效的,但我不知道如何在URL中显示更改 :) - Adam Halasz
    确切地说,@Matchu,Facebook是一个非常好的例子。 - Adam Halasz
    7个回答

    25
    对于你问题中链接的演示,实现该功能非常简单 - 因为它根本不使用任何AJAX(当你开始将AJAX添加到其中时,它会变得更加困难 -稍后解释)。要实现该功能,您需要升级链接以使用哈希,然后绑定到hashchange事件。不幸的是,hashchange事件不跨浏览器兼容,但幸运的是有许多“历史记录/远程插件”可用 - 多年来我们首选的插件已被证明是jQuery History,它是开源的,拥有出色的支持并且正在积极开发 :-)。
    尽管如此,当涉及将AJAX功能添加到诸如Facebook、WBHomesBalupton.com等网站时,您将开始面临一系列严重的问题! (我知道,因为我是最后两个网站的首席架构师!)。其中一些问题包括:
    • 如何优雅且轻松地升级特定内部链接以使用历史记录和AJAX功能,并检测哈希值何时更改?同时保持其他链接像以前一样工作。
    • 如何从"www.yoursite.com/myapp/a/b/c"重定向到"www.yoursite.com/myapp/#/a/b/c"?并尽可能让用户体验顺畅,使三个必要的重定向尽可能平滑。
    • 如何使用AJAX提交表单值和数据并更新哈希值?如果不支持Javascript,则反之亦然。
    • 如何检测AJAX请求想要的特定页面区域?这样子页面就能正确地显示出来了。
    • 当AJAX状态改变时如何更改页面标题以及其他非页面内容。
    • 如何在AJAX状态加载和更改时执行漂亮的介绍/退出效果?这样用户就不会被置于黑暗中。
    • 如何通过AJAX登录后更新侧边栏登录信息?因为显然我们不再想让那个左上角的登录按钮存在了。
    • 如何仍然支持没有启用JS的用户?以便它能够优雅地降级并仍然可以被搜索引擎索引。
    我所知道的唯一一个开源且可靠的项目,尝试解决所有那些极为困难的问题,被证明是jQuery Ajaxy。它实际上是之前提到的jQuery History项目的扩展,提供了一个漂亮而优雅的高级接口来添加AJAX功能,处理幕后的那些困难问题,使我们不必担心它们。它也是最近几个商业站点中所选择的解决方案。
    祝你好运,如果有任何进一步的问题,请在此回答下方发表评论,我会尽快回复:-)
    更新:现在有HTML5 History API(pushState,popState),它取代了HTML4中的hashchange功能。History.js现在是jQuery History的继承者,并为HTML5 History API提供跨浏览器兼容性以及HTML4浏览器的可选hashchange回退。jQuery Ajaxy将升级为History.js。

    1
    嗨!非常感谢您的回答,我知道我的演示不是用AJAX制作的,但是我将使用AJAX来制作自己的演示,但是那个演示展示了我想要实现的效果。您的例子:http://wbhomes.com.au/#/home非常酷,这正是我想要的100%,没有和其他东西,但对我来说,任何可行的版本都可以,如果您能向我展示如何制作它,我会非常非常高兴:)。我知道这非常困难,因为没有人发布(我没有找到)有关它的任何内容,而且我真的不知道如何制作它,我不是JavaScript专业人员。 - Adam Halasz
    谢谢伙计,我很高兴能帮到你。是的,我完全同意wbhomes网站非常酷!我修改了我的帖子,详细介绍了使用的解决方案(jQuery Ajaxy),这样应该可以消除任何遗漏的问题:-)如果你想知道更多信息,请随时发表评论,或者你可以直接在我的网站www.balupton.com上联系我。 - balupton
    嗨@balupton!Ajaxy很好,很酷,但我认为它存在一个巨大的问题。我无法指定我想要放置“content”的位置。例如,我有“link1 - onclick调用page1.php”和“link2 - onclick调用page2.php”,但我希望“link1”更改“div content1”,而“link2”更改“div content2”,我希望你明白我在说什么:)我认为如果有了这个功能,它就几乎完美了;) - Adam Halasz
    嘿@Cirk。好观点,肯定是我也在考虑的事情。将其编码为vanilla JS并使用框架适配器是待办事项清单上的事情。目前的优先事项是发布驱动balupton.com的CMS,并记录如何使用Ajaxy进行一些非常高级/整洁的操作。关于您的观点,您能否在此处提出它们http://getsatisfaction.com/balupton/products/balupton_jquery_ajaxy作为这样我将更好地处理问题:-)现在已经很晚了,所以我要去睡觉了。但是非常高兴继续这个对话! - balupton
    谢谢你的快速回复 @baluton!很高兴听到你想要做这件事!我真的很开心,也非常感激你的辛勤工作!晚安! - Adam Halasz
    显示剩余2条评论

    1

    你好.. :)

    HTML

    <a href="/bye.php?user=abc&page=messages" 
       onclick="return goToWithAjax(this);">bye</a> 
    

    Javascript

    function goToWithAjax(hash) {
      hash = hash.href ? hash.getAttribute("href", 2) : hash;
      ajax( hash, function( response ) {
        document.getElementById("content").innerHTML = response;
      });
      hash = ("#!/" + hash).replace("//","/");
      window.location.hash = hash;
      return false;
    }
    
    //////////////////////////////////////////////////////////////////////////////
    
    function getXmlHttpObject() {
        var xmlHttp;
        try {
            xmlHttp = new XMLHttpRequest();
        } catch (e) {
            try {
                xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
            } catch (e) {
                xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
        }
        return xmlHttp;
    }
    
    function ajax(url, onSuccess, onError) {
        var xmlHttp = getXmlHttpObject();
        xmlHttp.onreadystatechange = function () {
            if (this.readyState == 4) {
                // onError
                if (this.status != 200) {
                    if (typeof onError == 'function') {
                        onError(this.responseText);
                    }
                }
                // onSuccess
                else if (typeof onSuccess == 'function') {
                    onSuccess(this.responseText);
                }
            }
        };
        xmlHttp.open("GET", url, true);
        xmlHttp.send(null);
        return xmlHttp;
    }​
    

    看我的更新,现在你有一个相当通用的解决方案。 :) 你可以使用文件名或带有哈希的url。在这种情况下,您还可以指定文件扩展名,默认为php。 - gblazex
    那么我应该把$hash放在哪里?是在messages.php还是其他地方? - Adam Halasz
    1
    在你的每个站点中都加入ajax。这将有助于恢复ajax事物,例如当用户从链接进入时。 - gblazex
    啊,这个用匈牙利语怎么说啊 :D 现在我来问这里了,因为我不明白。xD 我不知道如何使用 $hash,需要调用的文件是 ajax,应该把它放在那些被 ajax 调用的文件中吗?如果是的话,我应该在那里做什么? - Adam Halasz
    @George Fritzsche,当然,这是我说的:我不明白如何使用$hash, ajax需要包含的文件是messages.php。 我需要把$hash放到ajax邀请的文件中吗? 如果是这样,我该怎么做? - Adam Halasz
    显示剩余18条评论

    1
    我认为你可以很容易地使用HTML5中存在的onHashChange事件或者使用一个模拟浏览器中“哈希”行为的JavaScript库来实现它。其中一个这样的库可能是MooTools onhashchange,但也有许多其他选择。
    如果你有一个支持HTML5的浏览器,或者使用类似的库来模拟这种行为,那么只需使用
    window.sethash("#newsection");
    从JavaScript更改到新的内容,并/或使用回调来拦截onHashChange事件,具体取决于你的用例场景。

    1
    实际上,使用onhashchange是大多数人的做法 - 包括Gmail在内。 - A. Ionescu
    问题在于许多浏览器不支持原生的onhashchange,或者它们存在一些怪异行为。提供的库可以为旧版浏览器添加支持,但这只是钩入哈希值的功能,与AJAX范式的工作方式关系不大。 - balupton

    1

    CorMVC Jquery Framework 是以这种方式完成的,它是开源的,您可以深入源代码并从中获取逻辑。

    实际上,它非常直截了当。创建者在下面的视频中很好地讲解了它。

    http://www.bennadel.com/resources/jing/2009-12-21_0933.swf

    抱歉,因为我是新用户,所以无法发布第二个链接。


    0

    这是大多数新的AJAXian开发人员难以理解的问题。但实际上,这是一个相当简单的问题。

    首先,您需要的是jQuery核心,可以在jquery.com免费下载。

    接下来,您需要Ben Alman的jQuery哈希更改插件,您可以在此处找到:http://benalman.com/projects/jquery-hashchange-plugin/ 对于支持html5哈希更改事件的较新版本的浏览器,您不需要此插件,但对于旧版本的浏览器,您需要它。您只需将此脚本包含在页面中即可,它会处理其余部分。

    现在,对于您的链接,您需要以查询字符串方式构建它们,如下所示:

    <a href="user.php?q=/topic/article" class="dynlnk">Link Text/Image</a>
    

    现在您有链接可以转到页面,并且可以在 PHP 中处理,以防 JavaScript 被关闭。您只需要使用超级全局变量 $_GET 并解析查询字符串来处理页面内容。

    现在在您的页面上的 JavaScript 中,您需要使您的链接触发哈希更改。您可以通过将 ?q= 替换为 # 来实现。

    $(".dynlnk").each(function(){
        $(this).attr("href", $(this).attr("href").replace("?q=", "#"));
    });
    

    现在您的链接将触发哈希更改,唯一剩下的事情就是将哈希更改绑定到执行某些操作的函数上。这可以使用jQuery非常简单地完成,如下所示:

    $(window).bind( 'hashchange', function(e){
    
        //this splits the part after the hash so you can handle the parts individually.
        //to handle them as one just use location.hash
        pageparts = location.hash.split("/");
    
    });
    

    现在只需添加处理您的ajax和内容的任何代码。

    现在你只需要最后一点javascript来触发hashchange,以防页面最初加载时有一个哈希,所以当页面加载时只需调用窗口触发函数即可。

    $(window).trigger( 'hashchange' );
    

    希望这已经足够清晰了,如果还有疑问,请随时联系我提出更多问题。

    0
    使用哈希链接可以创建可书签化/可共享的链接来触发JavaScript代码,而不是重新加载页面。Ben Almans jQuery hashchange event 允许你绑定一个事件处理程序到哈希更改事件上,这个插件适用于通常不支持此功能的旧浏览器。绑定到哈希更改的事件处理程序可以读取URL的哈希部分,并调用任何函数。
    // register event handler
    function bindHashchange() {
    
        $(window).bind('hashchange', function(event) {
            event.preventDefault();
            var label = location.hash.substring(1);
            handleLabel(label);
        });
    
        // trigger event so handler will be run when page is opened first time
        // otherwise handler will only run when clicking on hash links
        $(window).trigger('hashchange');
    }
    
    // read and handle hash part of url
    function handleLabel(label) {
    
        if ( label.length > 0 ) {
            // using label from url
            switchPage(label);
        } else {
            // use the default label, if no hash link was present
            switchPage('start');
        }
    }
    
    // in this case, load hidden <div>'s into a <div id="content">
    function switchPage(label) {
        if ( label == 'start ) {
            $('div#content').html($('div#start'));
        } else if ( label == 'some_other_page' ) {
            // do something else
        }
    }
    

    这个事件处理程序可以处理在同一个URL中由点('.')分隔的2个参数。

    function processHash() {
    
        var str = location.hash.substring(1);
        var pos = $.inArray('.', str);
    
        var label = '';
        var arg = '';
    
        if ( pos > -1 ) {
            label = str.substring(0, pos);
        } else {
            label = str.substring(0);
        }
    
        if ( pos > 1 ) {
            arg = str.substring(pos+1);
        }
    
        if ( label.length == 0 ) {
            // the default page to open of label is empty
            loadContent('start');
        } else {
            // load page, and pass an argument
            loadContent(label, arg);
        }
    }
    

    如果使用正则表达式,可以解析任何字符组合。

    var registry = {};
    
    // split on character '.'
    var args = label.split(/\./g);
    
    for ( i in args ) {
        var arg = args[i];
    
        // split on character '='
        var temp = arg.split('=');
        var name = temp[0];
        var value = temp[1];
    
        // store argument in registry
        registry[name] = value;
    }
    // registry is loaded, ready to run application that depends on arguments
    

    这将转换URL:

    mysite/#company.page=items.color=red

    将其转换为以下JavaScript对象:

    Object { company=undefined, page="items", color="red"}

    然后只需要在所选元素上运行jQuery的show()或hide()函数即可。

    这可以转换为非jQuery JavaScript,但那样你将失去Ben Alman提供的关键功能,这对于可移植解决方案至关重要。


    0
    你需要的是一种支持 AJAX 中的 历史记录 的方法,这可以使用许多已经存在的库来实现。我建议阅读 YUI 3 page on history

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