【问题标题】:How to handle non-root URLs in a singlepage app?如何在单页应用程序中处理非根 URL?
【发布时间】:2012-08-18 10:31:27
【问题描述】:

我尝试使用 Rails 3.2 和 Backbone.js 制作带有 pushState 选项的单页应用程序,但遇到了一些我不理解的问题。

如果我加载应用程序的根 URL (/),一切正常:Rails 返回一个带有 JS 的 HTML 布局,它引导 Backbone,它为 JSON 实体生成一些 XHR 并呈现内容。

但是如果我从 non-root URL 开始使用应用程序(例如,通过在浏览器的地址栏中手动输入),那么 Rails 将尝试使用来自 routes.rb 的路由规则来处理此请求 -这是错误的,因为它是“骨干”路线。在这种情况下,如何加载页面和引导 Backbone 以处理此 URL?

【问题讨论】:

    标签: backbone.js routing ruby-on-rails-3.2 singlepage


    【解决方案1】:

    我终于找到了解决办法。

    我将以下代码放入我的 routes.rb 中

    class XHRConstraint
      def matches?(request)
        !request.xhr? && !(request.url =~ /\.json$/ && ::Rails.env == 'development')
      end
    end
    
    match '(*url)' => 'home#index', :constraints => XHRConstraint.new
    

    使用这个匹配器,所有非 XHR 请求都被路由到返回 HTML 页面的 HomeController。 XHR 请求将由返回 JSON 响应的其他控制器处理。 我还留下了以“.json”结尾的请求在开发环境中有效以进行调试。

    【讨论】:

    • 我还发现这个 great write-up by artsy 描述了如何使用 Backbone pushState 创建一个全局链接处理程序以避免页面刷新,我觉得这与这个答案非常结合,可能会对某些人有所帮助。跨度>
    • 谢谢你!为了能够在 Rails 4 中工作,必须更改此行:get '*path' => 'home#index', :constraints => XHRConstraint.new
    【解决方案2】:

    这是一个有点棘手的问题,但基本上简而言之,您需要使用相同(根)页面响应 rails 中的所有有效(HTML)请求,从那里主干将接管并路由到正确的路由处理程序(在您的 bakckbone 路由器中)。

    我在这里更详细地讨论了这个问题:rails and backbone working together

    基本上我所做的是为我想要处理的每个页面和空白视图创建操作。我使用respond_with 来返回页面(在每种情况下都是相同的),并且因为我为 HTML 请求处理 GET 操作 only,所以我在控制器顶部添加了这一行:

    respond_to :html, :only => [ :show, :new ]
    

    JSON 请求也使用 respond_with 处理,但与 HTML 请求不同,它实际上返回请求的资源(并在 PUTPOSTDELETE 的情况下执行请求的操作)。

    【讨论】:

    • 用更多信息更新了我的答案。
    • 这可以解决问题,但不是太优雅,因为所有 Backbone 的路由都必须由 Rails 负责。因此,当您更改客户端的路由时,您必须更新服务器路由。真的没有办法将所有的html请求委托给根控制器吗?
    • 我不同意:如果您将 all 请求委托给根控制器,那么您就是说所有请求都是有效的,而实际上大多数请求都不是。 Rails 需要知道哪些路由有效,哪些无效,以便正确返回错误路由的状态代码等。这是重复,但它是重要的重复。一旦你开始使用 pushState,这是不可避免的。
    • 是的,如果我将所有 html 请求委托给根控制器,我假设所有 html 请求都是有效的,因为它是一个单页应用程序,并且任何 html 请求都应该返回根页面。我不同意 Rails 需要了解客户的路由,因为他们的管理是 Backbone 的路由器业务。 Rails 是无状态的,没有“页面”或“动作”,只有资源(只能由 XHR 访问)和根页面。
    • 谢谢 :) 针对您的最后一点,我想说:那您为什么要使用 pushState?在我看来,正常的散列/锚定方法就是你想要的。 pushState 旨在帮助您使您的页面可以作为 HTML 资源访问,这就是为什么(我相信)rails 应该知道他们的路线等。
    【解决方案3】:

    如果您手动操作,Backbone 将不会被告知您的 url 更改。此更改将被浏览器捕获,并且会像往常一样将请求发送到服务器。

    如果你点击一个普通的链接,它会跟随它的href而不通知Backbone。

    如果您希望 Backbone 负责更改 url,您必须通过可用的 Backbone 工具来完成,这是自己的路由器。

    因此,如果您想以 Backbone 方式更改 URL,则必须明确地进行,例如:

    app.router.navigate("my/route", {trigger: true});
    

    【讨论】:

      猜你喜欢
      • 2017-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-17
      • 1970-01-01
      • 2012-10-09
      • 1970-01-01
      • 2015-08-13
      相关资源
      最近更新 更多