Turbolinks 實例:為什麼 scroll 報錯?來給 jQuery event 取個名稱
喜歡作者的文章嗎?馬上按「關注」,當作者發佈新文章時,思書™就會 email 通知您。
思書是公開的寫作平台,創新的多筆名寫作方式,能用不同的筆名探索不同的寫作內容,無限寫作創意,如果您喜歡寫作分享,一定要來試試! 《 加入思書》
思書™是自由寫作平台,本文為作者之個人意見。
給本文個喜歡
或不
關於作者
很久以前就是個「寫程式的」,其實,什麼程式都不熟⋯⋯
就,這會一點點,那會一點點⋯⋯
看看作者的其他文章
看看思書的其他文章
我剛剛碰到了一個有趣的問題,我要用 jQuery 來檢查網頁的位置,當網頁轉到那裡時,就把一個 DOM 顯示出來,很簡單,就給 window 裝上一個 scroll event 吧:
如果你是在沒有 Turbolinks 的環境下,就這麼簡單,但是,這樣的一個簡單功能,在 Turbolinks 上,馬上就會有問題了,你第一頁不會有問題,但是點選網頁的連結後,就會一直看到聯覽器的 console 上,不斷的說找不到 #JS-target,你會覺得很奇怪,明明這個連結的網頁並沒有這個 Javascript,為什麼還會執行?
如果你還沒有看過我寫的這篇文章:
Rails Turbolinks™ 5 深度研究 — 不管你是愛、還是恨(說得有點超過),但是真的很多 Rails 人乾脆把 Turbolinks 關掉了。 我還是繼續使用中... 什麼是...
Scrivinor 思書: 紅寶鐵軌客
我建議有空可以看看,只是還蠻長的,如果你很急著要知道答案,我就直接說:問題的根源就是,Turbolinks 已經把你的網頁變成 SPA(Single Page Application,單頁式應用網站)了。
在 Turbolinks 使用中,你點選了一個連結,Turbolinks 只是把 <body> 的內容換掉了,<head> 的內容都保留,更重要的是,你曾經掛上的 Javascript event,當然也被保留了,這也就是這個 scroll event 為什麼還會繼續執行的原因。
這 「SPA 單頁式應用網站」的觀念,是在使用 Turbolinks 中,最重要必須要了解的其中一項觀念,不然,你的 BUG 都會在點選網頁連結後發生,很多情況下,甚至不被發現!
那我們實務上要怎麼寫呢?下面是一個解法:
讓我們來看看這程式的重點:
$(document).on('turbolinks:load', function()
就不在此介紹了,這是一個很標準的 Turbolinks 取代$(document).ready()
的啟動方式。if ($('#JS-target').length > 0)
:先判斷目標 DOM 存不存在,如果存在,才執行需要的 Javascript,我覺得這是一個好習慣,先檢查這頁要不要執行需要的 Javascript,很多人沒寫,我不喜歡,我相信對效率一定有影響,特別是使用者長時間使用不同的網頁。$(window).on( "scroll.event_target", function()
:如果存在,就把 event 掛到 on scroll 上,這也是先前的程式,除了多了一個 event_target,這是什麼?我等一下專門說。$(window).off( "scroll.event_target" )
:如果不存在,就把這個 on scoll 的 event 卸載,off 掉,這就是針對 Turbolink 「SPA 單頁式應用網站」特別加上的,因為 Turbolinks 在跳轉到另一頁時,如前所述,你曾經掛上的 Javascript event,都會被保留,如果不把這個 event卸載 off 掉,它就會繼續執行,所以,增加的這一行是針對 Turbolinks 使用上,很重要的 。Event 的 namespace
如果看過我其他文章的人,因該都知道我很喜歡 jQuery,主要是 jQuery 對跨瀏覽器的相容性真是太好用了,電腦跑那麼快,給 jQuery 拖慢一些,我覺得還好啦,我應該是很少數敢公開說 jQuery 好話的人,大家現在談到 jQuery 好像都很不屑,好啦,廢話不多說,我們現在就來談談什麼是那個「event_target」,其實很簡單,就是給這個 event 取個名稱,這也是使用 jQuery 的一個小好處,就直接取名就好,這個 event 就叫做「event_target」,你如果用 Javascript 就要自己寫 namespace 了。
那為什麼要給這個 event 取個名稱呢?因為我們真的可以直接用 $(window).off( ) 卸載 off 掉所有的 event 但是你知道你其他的 Javascript 沒有用到 $(window) 這個物件嗎?$(window).off( "scroll" ) 也一樣,萬一別的地方也用的 scroll event,那你就是把它全關了,這可不行啊,這樣做,你以後只會抓蟲抓到昏倒,所以,你只能卸載 off 掉這一個 event,這一個名叫「event_target」的 event。
jQuery 如何 off 掉指定的 event?
結果,超簡單,只要給它取個名(namespace)就好了,在掛 event 時:
把它 off 掉時:
就這樣,超簡單好用!
$(window)
也是一個有趣的東西,它是 jQuery 包裹著window
的物件,而window
是一個 global 環境變數,照理,我給window
加上了一個 event,他就應該是 global 的,這樣,網頁上每一頁都會執行這個 event 了,是這樣嗎?我是沒試過啦,不知道有沒有人試過?參考:
Namespaced Events in jQuery | CSS-Tricks — It's really easy to add an event listener in jQuery. It's equally easy to remove an event listener. You might want to remove a listener because you don't CSS-Tricks