8

我目前正在尝试建立一个新网站,没什么特别的,又好又小,但我一开始就卡住了。我的问题是干净的 URL 和页面导航。我想以“正确的方式”去做。

我想拥有的:

  • 我使用 CodeIgniter 来获取干净的 URL,例如 “www.example.com/hello/world”
  • jQuery 帮助我使用 ajax,所以我可以 .load() 附加内容
  • 现在我想使用像 pushstate 这样的 HTML5 功能来摆脱 URL 中的 #

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

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

例如:
一个非常基本的网站。两个链接,称为“foo”和“bar”,它们下方有一个空的 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 文件夹会更好。

我看过的一些教程:

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

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


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


提前感谢您的帮助。如果您有建议、想法或简单的只想提点什么,请告诉我。

关于
迪勒

4

2 回答 2

9

我在这里提出了一个成功的 HTML5 历史最小示例:http: //cairo140.github.com/html5-history-example/one.html

在我看来,进入 HTML5 pushstate 的最简单方法是暂时忽略该框架并使用最简单的状态转换:大量替换<body>and<title>元素。在这些元素之外,标记的其余部分可能只是样板,尽管如果它发生变化(例如,如果您在后端更改 HTML 上的类),您可以适应它。

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

/one.html
/two.html
/assets/application.js

这些是我们正在使用的仅有的三个文件。

这是两个 HTML 文件的代码。如果您在处理 HTML5 功能时处于水平,您应该能够理解标记,但是如果我没有说清楚,请发表评论,我将引导您完成它:

一个.html

<!doctype html>
<html>
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.js"></script>
    <script src="assets/application.js"></script>
    <title>One</title>
  </head>
  <body>
    <div class="container">
      <h1>One</h1>
      <a href="two.html">Two</a>
    </div>
  </body>
</html>

二.html

<!doctype html>
<html>
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.js"></script>
    <script src="assets/application.js"></script>
    <title>Two</title>
  </head>
  <body>
    <div class="container">
      <h1>Two</h1>
      <a href="one.html">One</a>
    </div>
  </body>
</html>

您会注意到,如果您one.html通过浏览器加载,您可以单击指向 的链接two.html,这将加载并显示一个新页面。并且从two.html,你可以做同样的回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);
    });
});

这个怎么运作

replacePage在 jQuery 就绪回调中定义了在参数中直接加载 URL,并用远程检索的内容替换titleand元素的内容。.container

调用是指页面上live任何一个链接点击都会触发回调,回调将状态推送到href链接中的 并调用replacePage。它还用于e.preventDefault防止链接被正常处理。

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

如何扩展它

这个非常基本的示例可以或多或少地移植到任何站点,因为它进行了非常没有创意的转换:HTML 替换。我建议你可以以此为基础,过渡到更有创意的过渡。您可以做的一个示例是模拟 Github 在其存储库中使用目录导航所做的事情。这是一个需要浮动和溢出管理的中间操作。您可以从更简单的过渡开始,例如将.container加载页面中的 附加到 DOM,然后将旧容器动画到{height: 0}.

解决您的特定“例如”

您在使用 HTML5 历史记录方面处于正确的轨道上,但您需要澄清您对包含哪些内容/foo/bar将包含哪些内容的想法。基本上,您将拥有三个页面://foo/bar/将有一个空的容器 div。/foo将与/容器 div 中包含一些 foo 内容的情况相同。除了容器 div 中包含一些 bar 内容之外,/bar将与 相同。/foo现在,问题是如何通过 Javascript 提取容器的内容。假设您的/foo body标签看起来像这样:

<body>
  <a href="/foo">foo</a>
  <a href="/bar">bar</a>
  <div class="container">foo</div>
</body>

然后你会从响应中提取它,然后data通过. 您使用而不是更合理的,因为出于某种古怪的原因,jQuery 的 DOM 解析器会生成一个 jQuery 对象,其中包含元素的每个子元素和元素的每个子元素,而不仅仅是包装元素的 jQuery 对象。我不知道为什么。var html = $(data).filter('.container').html()$('.container').html(html)filterfindheadbodyhtml

其余的只是将其改编回上面的“香草”版本。如果您被困在任何特定阶段,请告诉我,我可以为您提供更好的指导。

代码

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

于 2011-07-10T04:14:40.050 回答
2

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

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');
于 2012-03-19T15:53:04.007 回答