Stimulus 是一個簡單的 JavaScript 框架, 它最主要的特色是可以使用你現有的 HTML 去賦予他們生命 (類似於 Angular 1.0, 但是簡單許多).
在透過將試作型討戰網上的大大小小以 Stimulus 改寫後, 獲得了許多零散的心得. 若你對 Stimulus 有興趣, 但不知道是否該引入到目前的專案的話, 這篇筆記或許可以幫助到你.
專案背景簡介
- 試作型討戰網是一個 Ruby on Rails 網頁應用程式.
- 它不是一個 Single Page App, 也沒有在所有的地方都使用 React, 使用了 Turbolinks.
- 前端使用了 React 與 Redux 建構那些比較複雜的地方.
Stimulus 的吸引力
- 可以直接使用 Rails app 的 view, 不需要維護兩份.
- 可以用任何自己喜歡方式操作 HTML, 例如可以使用
insertAdjacentHTML
, 甚至可以直接使用innerHTML
. - Stimulus 透過使用 Mutation Observer 監視任何變更, 會自動綁定任何擁有 controller 的元素, 我甚至能做到在做某些事情後執行
el.setAttribute('data-controller', controllers)
去追加 controller. - 可以直接操作 DOM 在某些場合很方便, 這點在 React 挺麻煩的…
- 喜歡某個 jQuery plugin 但它沒有 React 版本, 你可以直接使用, 沒有額外煩惱.
- 如果你喜歡 UJS, 那你也一定會喜歡 Stimulus.
- 學習與開發成本非常低, 你是公司唯一的網頁開發者嗎? 這會是你的好朋友, 而且不會有任何 React 的前端開發者嘗試阻止你.
Stimulus 的麻煩點
- 直接操作 DOM 是一件很痛苦的事情, 不過這方面可以用 jQuery 讓自己少點痛苦. 也可以嘗試使用 Cash
- 與其他 controller 溝通不太方便, 它提供了
application.getControllerForElementAndIdentifier
方法, 但這名字長到怎麼看都不是鼓勵使用者頻繁使用的方法. - 另一個與其他 controller 溝通的方法是觸發 CustomEvent.
- 如果像我一樣不喜歡把所有的功能混一起寫, 那你可能會在 HTML 中看到大量的
data-controller
data-action
data-target
地獄.
如何與 React 元件溝通?
如果使用 Redux, 那最好的方式應該是使用 store.dispatch(action)
去更新 store, 讓它去影響 React 元件.
在 React 中使用 Stimulus controller?
我覺得可以, 但我還沒嘗試過, 如果只是做一些只操作某些 DOM 屬性的功能應該很適合吧.
像最後面附上的這個範例.
使用 Stimulus 完全取代 React?
可行, 但我認為他們的強項不同, 何時該用哪個完全是看情況而定.
範例
https://gist.github.com/ayamomiji/e755bb1b7f477840e4d66b8a2ba7acea
這是一個智慧捲動的範例: 在新元素被插入前, 如果捲軸已經捲動到最底下了, 就在插入元素後捲動到最後.
Stimulus 並不鼓勵與其他 controller 頻繁互動, 但我覺得在這個例子, 與 parent controller 溝通很方便, 因此寫了這個方法, 並且要求自己儘量最小幅度的使用它.
export function getParentController(controller, identifier) {
const application = controller.application
let element = controller.element
do {
let foundController =
application.getControllerForElementAndIdentifier(element, identifier)
if (foundController) {
return foundController
}
} while (element = element.parentElement)
}