使用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