CodeIgniter + jQuery(ajax)+ HTML5 pushstate:如何使用真实URL进行干净的导航?

我目前正在尝试建立一个新的网站,没有什么特别的,漂亮的和小的,但我一开始就陷入困境。 我的问题是干净的URL和页面导航。 我想以“正确的方式”做到这一点。

我想要的是:

  • 我使用CodeIgniter获取干净的url,例如“www.example.com/hello/world”
  • jQuery帮助我使用ajax,所以我可以.load()其他内容
  • 现在我想使用像pushstate这样的HTML5function来删除URL中的#

应该可以在没有页面刷新的情况下来回移动,但页面仍将根据当前URL显示正确的内容。

还应该可以重新加载页面而不会出现404错误。 由于CodeIgniter,该网站应该存在。 (有一个控制器和一个视图)

例如:
一个非常基本的网站。 两个链接,称为“foo”和“bar”,下面是一个emtpy div框。 基本URL是example.com
当您单击“foo”时,URL将更改为“example.com/foo”而不重新加载,div框将使用jQuery .load()获取新内容。 对于其他链接也是如此,当然不同的内容和URL。
单击“foo”然后“bar”后,后退按钮将返回“example.com/foo”并显示相应内容。 如果我直接加载此链接或刷新页面,它看起来会一样。 没有404错误或其他什么。

试想一下这个页面并告诉我你将如何做到这一点。 我真的很想拥有这种导航,所以我尝试了几件事。


至今…
我知道如何使用CodeIgniter来获取这样的URL。 我知道如何使用jQuery加载其他内容,虽然我不完全理解html5 pushstate的东西,但我至少让它以某种方式工作。 但我不能让它一起工作。 我现在的代码很乱,这就是我不想在这里发布它的原因。 我查看了不同的教程,并将一些代码粘贴在一起。 我想上传我的CI文件夹会更好。

我看过的一些教程:

  • 深入了解HTML5
  • HTML5演示
  • Mozilla操纵浏览器历史记录
  • Saner HTML5历史
  • Github:History.js

(达到的最大链接数量:/)

我认为我的主要问题是,每个人都试图让它与所有浏览器和不同版本兼容,添加脚本/ jQuery插件等等,我对所有其他代码感到困惑。 我的脚本标签和实际的html内容之间有更多代码。 有人可以发布最基本的方法如何在我的示例页面中使用HTML5吗?


失败的尝试:
在我的测试页面上,当我返回时,URL会更改,但div框仍将显示相同的内容,而不是旧的内容。 我也不知道如何根据链接中的href属性更改脚本中的URL。 是否有类似$(this).attr(’href’)的东西,根据我点击的链接而改变? 现在我必须为每个链接使用一个脚本,这当然是坏的。 当我刷新网站时,CodeIgniter启动并加载视图,但实际上只是视图本身,我用ajax加载的视图,而不是整个页面。 但我想这应该很容易修复布局和正确的控制器设置。 还没有太在意这个。


在此先感谢您的帮助。 如果您有任何建议,想法或简单的想提及的话,请告诉我。

问候
DILER

我在这里提出了一个成功的HTML5历史最小例子: http : //cairo140.github.com/html5-history-example/https://stackoverflow.com/questions/6638738/codeigniter-jqueryajax-html5-pushstate-how-can-i-make-a-clean-navigation/one.html

在我看来,进入HTML5 pushstate的最简单方法是暂时忽略框架并使用最简单的状态转换:批量替换元素。 在这些元素之外,标记的其余部分可能只是样板文件,但如果它有所不同(例如,如果您在后端更改HTML类),则可以对其进行调整。

像CI这样的动态后端基本上是伪造在特定位置(由URL标识)的数据的存在,通过动态生成它。 我们可以通过逐字地创建资源并将它们放置在您的Web服务器(可能是Apache)将简单地识别它们并通过它们提供它们的位置来抽象出框架的效果。 相对于域根,我们将有一个非常简单的文件系统结构:

 /https://stackoverflow.com/questions/6638738/codeigniter-jqueryajax-html5-pushstate-how-can-i-make-a-clean-navigation/one.html /https://stackoverflow.com/questions/6638738/codeigniter-jqueryajax-html5-pushstate-how-can-i-make-a-clean-navigation/two.html /assets/application.js 

这是我们正在使用的唯一三个文件。

这是两个HTML文件的代码。 如果您处理HTML5function时达到了这个水平,那么您应该能够理解标记,但如果我没有说清楚,只需发表评论,我将引导您完成它:

https://stackoverflow.com/questions/6638738/codeigniter-jqueryajax-html5-pushstate-how-can-i-make-a-clean-navigation/one.html

      One   

One

Two

https://stackoverflow.com/questions/6638738/codeigniter-jqueryajax-html5-pushstate-how-can-i-make-a-clean-navigation/two.html

      Two   

Two

One

您会注意到,如果您通过浏览器加载https://stackoverflow.com/questions/6638738/codeigniter-jqueryajax-html5-pushstate-how-can-i-make-a-clean-navigation/one.html ,则可以单击指向https://stackoverflow.com/questions/6638738/codeigniter-jqueryajax-html5-pushstate-how-can-i-make-a-clean-navigation/two.html的链接,该链接将加载并显示新页面。 从https://stackoverflow.com/questions/6638738/codeigniter-jqueryajax-html5-pushstate-how-can-i-make-a-clean-navigation/two.html ,你可以回到https://stackoverflow.com/questions/6638738/codeigniter-jqueryajax-html5-pushstate-how-can-i-make-a-clean-navigation/one.html 。 凉。

现在,对于历史部分:

资产/ application.js中

 $(function(){ var replacePage = function(url) { $.ajax({ url: url, type: 'get', dataType: 'html', success: function(data){ var dom = $(data); var title = dom.filter('title').text(); var html = dom.filter('.container').html(); $('title').text(title); $('.container').html(html); } }); } $('a').live('click', function(e){ history.pushState(null, null, this.href); replacePage(this.href); e.preventDefault(); }); $(window).bind('popstate', function(){ replacePage(location.pathname); }); }); 

这个怎么运作

我在jQuery ready回调中定义了replacePage ,以便在参数中直接加载URL,并将title.container元素的内容替换为远程检索的内容。

live呼叫意味着点击页面上的任何链接都将触发回调,并且回调将状态推送到链接中的href并调用replacePage 。 它还使用e.preventDefault来防止以正常方式处理链接。

最后,有一个popstate事件在用户使用基于浏览器的页面导航(后退,前进)时触发。 我们将一个简单的回调绑定到该事件。 值得注意的是,我无法在Dive Into HTML页面上获得该版本在FF for Mac中出于某种原因工作。 不知道为什么。

如何扩展它

这个极其基本的例子可以或多或少地移植到任何网站上,因为它做了一个非常无创造的过渡:HTML替换。 我建议您可以将此作为基础并转换为更具创意的过渡。 您可以做的一个例子是模拟Github对其存储库中的目录导航所做的事情。 这是一个需要花车和溢流管理的中间件。 您可以从更简单的转换开始,例如将加载页面中的.container附加到DOM,然后将旧容器设置为{height: 0}

解决您的具体“例如”

您正在使用HTML5历史记录,但是您需要明确您对https://stackoverflow.com/foohttps://stackoverflow.com/bar将包含的内容的想法。 基本上,你将有三个页面: /https://stackoverflow.com/foohttps://stackoverflow.com/bar/将有一个空的容器div。 https://stackoverflow.com/foo将与/ except相同,因为容器div中包含一些foo内容。 https://stackoverflow.com/barhttps://stackoverflow.com/foo相同,只是容器div中有一些条形内容。 现在,问题是如何通过Javascript提取容器的内容。 假设你的https://stackoverflow.com/foo body标签看起来像这样:

  foo bar 
foo

然后你将通过var html = $(data).filter('.container').html()从响应data提取它,然后通过$('.container').html(html)将它放回到父页面$('.container').html(html) 。 您使用filter而不是更合理的find因为从一些古怪的原因,jQuery的DOM解析器生成一个jQuery对象,其中包含head每个子项和body元素的每个子项,而不仅仅是包装html元素的jQuery对象。 我不知道为什么。

其余的只是将其重新调整为上面的“香草”版本。 如果您遇到任何特定阶段,请告诉我,我可以更好地指导您。

https://github.com/cairo140/html5-history-example

在你的控制器中尝试这个:

 if (!$this->input->is_ajax_request()) $this->load->view('header'); $this->load->view('your_view', $data); if (!$this->input->is_ajax_request()) $this->load->view('footer');