使用Turbolink开发应用程序确实需要特定的方法才能让事情顺利进行。由于页面加载和缓存的方式不同,某些运行脚本模式的行为与Turbolinks和不使用相同。这可能起初看起来并不友好,而“陷阱”可能令人沮丧,但我发现,通过一点理解,它鼓励更有组织,更健壮的代码:)
正如你所想,复制问题开关是插件在同一个元素上被多次调用。这是因为Turbolinks在导航离开它之前缓存了一个只是,因此缓存的版本包括任何动态添加的HTML [1],例如东西通过插件添加。在导航回退/前进时,缓存的版本将被恢复,并且行为将被重复:/
那么如何解决这个问题?在处理添加HTML或事件侦听器的代码时,在页面缓存之前拆除行为通常是一个好主意。该Turbolinks事件是turbolinks:before-cache
。所以,你的安装/拆卸可能是:
// app/assets/javascripts/switches.js
$(document)
.on('turbolinks:load', function() {
$('.switch').bootstrapSwitch()
})
.on('turbolinks:before-cache', function() {
$('.switch').bootstrapSwitch('destroy')
})
这是因为所有的设置有点困难,以测试和拆除在事件处理程序完成。更重要的是,还有更多这样的案例,所以为了防止重复使用,您可能需要引入您自己的“迷你框架”来设置和拆除功能。以下内容将介绍如何创建基本框架。
以下是我们的目标:拨打电话window.App.addFunction
并注册一个名称和功能。该函数获取元素并调用插件。它返回一个对象与destroy
功能拆解:
// app/assets/javascripts/switches.js
window.App.addFunction('switches', function() {
var $switches = $('.switch').bootstrapSwitch()
return {
destroy: function() {
$switches.bootstrapSwitch('destroy')
}
}
})
以下工具addFunction
,增加存储功能,在functions
属性:
// app/assets/javascripts/application.js
// …
window.App = {
functions: {},
addFunction: function (name, fn) {
this.functions[name] = fn
}
}
我们会打电话给每个功能时,应用程序初始化,并每个函数调用的结果存储results
阵列中,如果它存在:
// app/assets/javascripts/application.js
// …
var results = []
window.App = {
// …
init: function() {
for (var name in this.functions) {
var result = this.functions[name]()
if (result) results.push(result)
}
}
}
特aring删除了应用涉及破坏任何结果调用destroy
(如果存在的话):
// app/assets/javascripts/application.js
// …
window.App = {
// …
destroy: function() {
for (var i = 0; i < results.length; i++) {
var result = results[i]
if (typeof result.destroy === 'function') result.destroy()
}
results = []
}
}
最后我们初始化和拆除应用:
$(document)
.on('turbolinks:load', function() {
window.App.init.call(window.App)
})
.on('turbolinks:before-cache', window.App.destroy)
所以把这个放在一起:
;(function() {
var results = []
window.App = {
functions: {},
addFunction: function (name, fn) {
this.functions[name] = fn
},
init: function() {
for (var name in this.functions) {
var result = this.functions[name]()
if (result) results.push(result)
}
},
destroy: function() {
for (var i = 0; i < results.length; i++) {
var result = results[i]
if (typeof result.destroy === 'function') result.destroy()
}
results = []
}
}
$(document)
.on('turbolinks:load', function() {
window.App.init.call(window.App)
})
.on('turbolinks:before-cache', window.App.destroy)
})()
函数现在独立于调用它们的事件处理函数。这种解耦有几个好处。首先它是更可测试的:功能可在window.App.functions
中获得。您也可以选择何时调用您的功能。例如,假设您决定不使用Turbolinks,则只需调用window.App.init
即可。
[1]我想这是不是默认的浏览器的行为(如果按“后退”返回用户返回到页面,因为它是第一次加载时它)更好。 Turbolinks“Back”将用户返回到页面,这可能是用户期望的。
我只是经过并且对TurboLinks不太了解,但我认为这是一个简单的解决方法...尝试编写一个包装函数来测试是否在调用'.bootstrapSwitch();'之前并且只调用它在第一次运行... – Myst