請教 redux 與 eventEmitter?
最近一個小項目中(沒有使用 react),因為事件、狀態變化稍多,想用 redux 管理,可是並沒有發現很方便。
舉個例子:
store.subscribe(function() {
...
})store.dispatch({
type: "add",
value: 1
})store.dispatch({
type: "minus",
value: 1
})
這樣每次數據更新後的 DOM 修改就要在 subscribe 中完成。這樣也比較亂了。
還不如直接用 eventEmitter:
event.on("add", function(value) {
..
})event.on("minus", function(value) {
..
})btn1.on("click", function() {
event.emit("add", 1)
})btn2.on("click", function() {
那麼請問,在一般的小項目中,是怎麼管理數據狀態和事件的呢?
event.emit("minus", 1)
})
剛好在維護一個用 jQuery 的項目,也剛好用了 Redux 來進行數據管理。其實還挺好用的,但是你地做點手腳。不能純用 Redux,純用 Redux 還不如用 EventEmitter。
為什麼用 Redux 和 React 用起來還比較方便,是因為有了 React-redux 這個 Binding。它做了很多事情,它把你本來應該做的 subscribe、dispatch 都隱藏掉了,讓你只需要把 mapStateToProps 和 mapDispatchToProps 對象構造出來就好了。你試試不用 React-redux 的情況下在 React 裡面使用 Redux 試試看?就會遇到一樣的痛苦。
所以在普通項目裡面用 Redux 我們也需要在特定場景下做一個 Binding,也就是基於 Redux 做一層封裝就可以很好地達到我們需要的便利性。我們可以對照一下 React-redux,React 裡面每一個組件就相當於你項目中的每一個 render 方法,例如:
function renderTags (tagsState) {
var tags = tagsState.tags
var selectedTagName = tagsState.selectedTagName
$("#problem-tags").html(tags.map(function (tag) {
var $el = $("&")
if (tag === selectedTagName) $el.addClass("selected")
return $el
))
})
}
你可以把它想像成 React 裡面的某個組件,tagsState 是傳進去的 props。現在假設我們有一個 store,現在要把 store 裡面的數據取出來然後傳給 renderTags,並且在數據變化的時候重新 renderTags。這種事情在 React-redux 裡面都是 connect 幫你幹了,所以我們可以模擬它做一個叫 makeConnect 的庫函數(老舊項目,用的是 ES5,直接 copy 過來):
function makeConnect (store) {
return function connect (mapStateTopProps, render) {
var props = mapStateTopProps(store.getState())
store.subscribe(rerender)
/* 根據渲染函數返回一個新的渲染函數,這個函數會根據 state 裡面的數據做性能優化 */
function rerender () {
var newProps = mapStateTopProps(store.getState())
if (shallowEqual(props, newProps)) return /* 沒有變化就不用動了 */
render(newProps)
props = newProps
}
render(props)
return rerender
}
}
makeConnect 只需要寫一次,它就是我們所謂的 Binding它接受一個 store 返回一個 connect 函數,這個 connect 函數可以像 React-redux 的 connect 函數那樣使用。connect 函數接受組件(render 函數)和 mapStateTopProps ,並且從 state 裡面取出數據傳給 render 方法。在業務代碼中,我們構架完 store 以後就開始構建 connect:
connect = makeConnect(store)
然後就可以用這個 connect 去 connect 組件(也就是我們的 render 函數),所以其實最後寫起來像是:
function mapStateToProps (state) {
return {
tags: state.tags,
selectedTagName: state.selectedTagName
}
}
function renderTags (tagsState) {
var tags = ["全部"].concat(tagsState.tags)
var selectedTagName = tagsState.selectedTagName
$("#problem-tags").html(tags.map(function (tag) {
var $el = $("&")
if (tag === selectedTagName) $el.addClass("selected")
return $el
}))
}
/* 和 React-redux 一樣進行 connect */
renderTags = connect(mapStateToProps, renderTags)
其實除了 組件部分不一樣,其他都跟 React-redux 一樣。當然這個 makeConnect 方法還有可以改進的地方,有興趣的朋友可以一起開個 GitHub repo,本人用起來感覺還是挺方便的(和 jQuery)。
(以上內容根據真實項目代碼改編,如有雷同,算你抄我。)
謝邀。
如果你不用 react/vue 這種 mvvm,用 redux 不是自虐么。
react/vue 會自動由 state 產生 virtual dom ,由 virtual dom 算出 dom patch,然後應用到 dom 上,這一步總要去做的,區別就在於你每次更改數據都去手動完成,還是交給庫。
正因為 view 是 model/state 的忠實反映,用了 react/vue 之後,應用開發者只需要保證 state 里的數據是對的。
而 redux 只是方便開發者管理 store 以及綁定 store - component state 用的,view怎麼 patch,它可不管。對於小型項目,如果你覺得event更好用,那就用event,沒問題,絕對沒問題!畢竟小型項目就你一個人維護的話,就用自己最熟悉的技術就好了,又開心又順手。
Redux這樣的數據管理框架,在小型項目中會顯得啰嗦,一個小功能也要寫一堆action/reducer,呵呵,隨著項目變大,參與人增多,這套看起來啰嗦的方式就體現出優勢,結構更加清晰,數據更容易跟蹤。
了解更多Redux知識請關注 @程墨Morgan 和 「進擊的React」 http://zhuanlan.zhihu.com/advancing-react 專欄。講道理你應該用React而不是Redux。Redux的作用是管理狀態,使得狀態可觀察可預知,這其實對中小型的應用沒什麼幫助。如果問題只是事件多,狀態變化略複雜,那麼直接用React component的自帶狀態管理就足夠了。你現在的主要矛盾還是直接操作dom帶來的代碼調理不清晰,直接用React就可以解決了。圖是從這裡React.js Introduction For People Who Know Just Enough jQuery To Get By 扒的。
你可以考慮使用 MobX,它比 Redux 簡單些。
建議你用vue,如果你覺得用redux不方便,可能根本就不需要用redux,這也是redux作者本身的觀點
推薦閱讀:
※react redux 某個state變化之後 如何觸發一些操作?
※redux到mobx到dob……前端發展好快?
※感覺redux寫起來很麻煩,目前有那些其他的狀態管理方案?
※redux 中的 state 樹太大會不會有性能問題?