Turbolinks 补充

简单理解概念:把原来所有 GET 请求(包括链接、重定向、浏览器的后退)都通过 AJAX 来实现,并且 url 是变化的。

使用 turblinks 的话,注意:一,尽量从 AJAX 的角度出发写监听事件;二,尽量使用 turblinks 提供的监听事件。

Ruby 部分

重写了 ActionController::Base 里的 redirect_to 和 render 方法

ActionController::Base.ancestors.select{|a| a.to_s =~ /^Turbolinks/}
 => [Turbolinks::XHRHeaders, Turbolinks::Cookies,
     Turbolinks::XDomainBlocker, Turbolinks::Redirection]

render 使用的是 Turbolinks.replace redirect_to 使用的是 Turbolinks.visit

处理 :back 这种情况,使用 X-XHR-Referer 标识

更改了 url_for 方法(会影响到 link_to 等调用到它的方法)

当 url_for 使用到 :back 参数时有用,它会把原来 header 里的 HTTP_REFERER 改为 HTTP_X_XHR_REFERER

原因:Turbolinks 获取内容的时候使用 XMLHttpRequest 发起请求(简称 XHR)

带来的问题:XHR 请求的 HTTP 头 Referer 并不正确

解决办法:添加了 X-XHR-Referer 头,后端程序获取 Referer 的时候,需要先取 X-XHR-Referer。

module XHRUrlFor
  def self.included(base)
    base.alias_method_chain :url_for, :xhr_referer
  end

  def url_for_with_xhr_referer(options = {})
    options = (controller.request.headers["X-XHR-Referer"] || options) if options == :back
    url_for_without_xhr_referer options
  end
end

# 辅助方法
def referer
  self.headers['X-XHR-Referer'] || super # super 就是 self.headers['Referer']
end
alias referrer referer

覆盖了 Redirect 的 call 方法,修复 redirect_to 里的 bug

注意:上面设置了头 X-XHR-Redirected-To

其它几点

一,3 个钩子

1) 因为 trublinks 改变了原来 redirect_to 的行为,带来了新的问题,然后它又提供了解决办法:

对应 redirect_to :back 这种情况,使用 X-XHR-Referer 标识;用 X-XHR-Redirected-To 记录重定向的目标地址。

2) 它怎么记录是非 GET 请求的呢?用 cookies 记录。

对于非 GET 请求,turblinks 是不起作用的。

3) 跨域重定向:

某种情况下,禁止访问。

JS 部分

所有对外 API

配置项:

cacheSize 默认缓存 10 个页面

transitionCacheEnabled 事务缓存?默认为 false

requestCachingEnabled 请求缓存?默认为 true

progressBar 进度条

currentState 当前状态 loadedAssets 加载资源

referer 后退链接

xhr 异步请求

所有事件:

具体做了什么事,如何实现,可以查看对应源代码,在此不做讨论。

一些特性

Transition Cache

前面不是说过 turblinks 默认可以缓存 10 个页面吗? 现在问题来了:如果我要访问一个已经存在缓存里的页面,它是"直接从缓存里取",还是"改为了 AJAX 实现重新从服务端取"呢?

默认还是从"改为了 AJAX 实现重新从服务端取"。不过,你可以通过以下配置,让它"直接从缓存里取":

Partial replacements

你可以使用

实现局部替换 HTML 文档内容。

坑及策略

事件的改变

1) 点击链接:

2) 而使用浏览器历史返回上一页:

3) 其它:

JS 要如何更改使用?

jquery.turbolinks 实践,请按照 AJAX 的方式写 JS 代码。

怎样防止浏览器缓存 Turbolinks 请求:

像 jQuery.ajax(url, cache: false), 会被追加 "_#{timestamp}" 到 GET 请求参数里。

如何移除

如果有 js 逻辑绑定了DOMContentLoaded 事件,就需要为 Turbolinks 做兼容

语法或历史遗留问题,可以使用以下方法:

几个 data-* 属性

原来的 DOM 操作怎么办?并且它们是非幂等的

DOM 操作最好是幂等。如果不是幂等的,你可以使用使用 page:load 而不是 page:change

其它类和对象

Click 管理着链接和点击事件,触发时会进行检查。如果符合 trublinks 则用 AJAX 执行请求,否则改用普通的请求。

ProgressBar 进度条。对应 class name 为 turbolinks-progress-bar

ProgressBarAPI 管理进度条可用的接口。有:

CSRFToken 管理 csrf token,提供接口:

Link 对于已经存在的链接,进行一些特殊处理。 比如,前面提到过的,有的链接不能使用 turblinks

各种浏览器不同引起的问题

如何替换链接?

由 JS 实现。

如何防止丢失 Referer ?

压根就没有丢失,只是原来的不能用,用新的 X-XHR-Referer

参考:

Turbolinks jquery.turbolinks

最后更新于

这有帮助吗?