html - CodeIgniter + jQuery(ajax) + HTML5 pushstate : How can I make a clean navigation with real URLs?

标签 html url codeigniter jquery pushstate

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

我想要的:

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

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

    也应该可以重新加载页面而不会出现 404 错误。由于 CodeIgniter,该站点应该存在。 (有一个 Controller 和一个 View )

    例如:
    一个非常基础的网站。两个链接,称为“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 文件夹。

    我看过的一些教程:
  • Dive into HTML5
  • HTML5 demos
  • Mozilla manipulating the browser history
  • Saner HTML5 history
  • Github: History.js

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

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

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

    在此先感谢您的帮助。
    如果您有任何建议、想法,或者只是想提点什么,请告诉我。

    问候
    迪勒

    最佳答案

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

    在我看来,进入 HTML5 pushstate 的最简单方法是暂时忽略该框架并使用最简单的状态转换可能:批量替换 <body><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 .凉爽的。

    现在,对于历史部分:

    Assets /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 并替换 title 的内容。和 .container远程检索的元素。
    live call 表示点击页面的任何链接都会触发回调,回调将状态推送到href在链接和电话replacePage .它还使用 e.preventDefault以防止链接以正常方式处理。

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

    如何延长它

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

    解决您的特定“例如”

    您在使用 HTML5 历史记录的正确轨道上,但您需要澄清您的想法 /foo/bar将包含。基本上,您将拥有三个页面:/ , /foo , 和 /bar . /将有一个空的容器 div。 /foo将与 / 相同除了在容器 div 中有一些 foo 内容。 /bar将与 /foo 相同除了容器 div 中有一些条形内容。现在,问题是如何通过 Javascript 提取容器的内容。假设您的 /foo body标签看起来像这样:
    <body>
      <a href="/foo">foo</a>
      <a href="/bar">bar</a>
      <div class="container">foo</div>
    </body>
    

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

    其余的只是将其调整回上面的“ Vanilla ”版本。如果您被困在任何特定阶段,请告诉我,我可以更好地指导您。

    代码

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

    关于html - CodeIgniter + jQuery(ajax) + HTML5 pushstate : How can I make a clean navigation with real URLs?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6638738/

    相关文章:

    javascript - 如何解决URL中重复参数的问题

    JAVA应用程序和ECLIPSE无法连接到互联网

    php - 在 mysql (codeigniter) 中插入一个外键值

    javascript - Firefox 中的 console.memory 等效项?

    javascript - 在这种情况下的解决方法是通过降低不透明度来保持 z 顺序?

    javascript - 没有 http ://or www 的 URL 正则表达式

    php - 初学者 CodeIgniter 概念 - 可重用的 View 代码,去哪里? ( helper ?)

    codeigniter - Form_validation 错误进入数组

    jquery - HTML5 窗口 Pane 代码

    html - 服务 mpeg-dash 的服务器有什么要求