標籤:

請教 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 = $("&

你可以把它想像成 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 = $("&

/* 和 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 樹太大會不會有性能問題?

TAG:React | Redux |