国产99久久精品_欧美日本韩国一区二区_激情小说综合网_欧美一级二级视频_午夜av电影_日本久久精品视频

最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當前位置: 首頁 - 科技 - 知識百科 - 正文

前端響應式編程的方案及其缺點的詳細介紹(附代碼)

來源:懂視網 責編:小采 時間:2020-11-27 15:24:28
文檔

前端響應式編程的方案及其缺點的詳細介紹(附代碼)

前端響應式編程的方案及其缺點的詳細介紹(附代碼):本篇文章給大家帶來的內容是關于前端響應式編程的方案及其缺點的詳細介紹(附代碼),有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。現實世界有很多是以響應式的方式運作的,例如我們會在收到他人的提問,然后做出響應,給出相應的回答。在
推薦度:
導讀前端響應式編程的方案及其缺點的詳細介紹(附代碼):本篇文章給大家帶來的內容是關于前端響應式編程的方案及其缺點的詳細介紹(附代碼),有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。現實世界有很多是以響應式的方式運作的,例如我們會在收到他人的提問,然后做出響應,給出相應的回答。在

本篇文章給大家帶來的內容是關于前端響應式編程的方案及其缺點的詳細介紹(附代碼),有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。

現實世界有很多是以響應式的方式運作的,例如我們會在收到他人的提問,然后做出響應,給出相應的回答。在開發過程中我也應用了大量的響應式設計,積累了一些經驗,希望能拋磚引玉。

響應式編程(Reactive Programming)和普通的編程思路的主要區別在于,響應式以推(push)的方式運作,而非響應式的編程思路以拉(pull)的方式運作。例如,事件就是一個很常見的響應式編程,我們通常會這么做:

button.on('click', () => { 
 // ...})

而非響應式方式下,就會變成這樣:

while (true) { 
 if (button.clicked) { // ...
 }
}

顯然,無論在是代碼的優雅度還是執行效率上,非響應式的方式都不如響應式的設計。

Event Emitter

Event Emitter是大多數人都很熟悉的事件實現,它很簡單也很實用,我們可以利用Event Emitter實現簡單的響應式設計,例如下面這個異步搜索:

class Input extends Component { 
 state = { value: ''
 }
 onChange = e => { this.props.events.emit('onChange', e.target.value)
 }
 afterChange = value => { this.setState({
 value
 })
 }
 componentDidMount() { this.props.events.on('onChange', this.afterChange)
 }
 componentWillUnmount() { this.props.events.off('onChange', this.afterChange)
 }
 render() { 
 const { value } = this.state 
 return ( <input value={value} onChange={this.onChange} />
 )
 }
}
class Search extends Component { 
 doSearch = (value) => {
 ajax(/* ... */).then(list => this.setState({
 list
 }))
 }
 componentDidMount() {
 this.props.events.on('onChange', this.doSearch)
 }
 componentWillUnmount() {
 this.props.events.off('onChange', this.doSearch)
 }
 render() {
 const { list } = this.state
 return ( <ul>
 {list.map(item => <li key={item.id}>{item.value}</li>)} </ul>
 )
 }
}

這里我們會發現用Event Emitter的實現有很多缺點,需要我們手動在componentWillUnmount里進行資源的釋放。它的表達能力不足,例如我們在搜索的時候需要聚合多個數據源的時候:

class Search extends Component { 
 foo = ''
 bar = ''
 doSearch = () => {
 ajax({
 foo,
 bar
 }).then(list => this.setState({
 list
 }))
 }
 fooChange = value => { this.foo = value this.doSearch()
 }
 barChange = value => { this.bar = value this.doSearch()
 }
 componentDidMount() { this.props.events.on('fooChange', this.fooChange) this.props.events.on('barChange', this.barChange)
 }
 componentWillUnmount() { this.props.events.off('fooChange', this.fooChange) this.props.events.off('barChange', this.barChange)
 }
 render() { // ...
 }
}

顯然開發效率很低。

Redux

Redux采用了一個事件流的方式實現響應式,在Redux中由于reducer必須是純函數,因此要實現響應式的方式只有訂閱中或者是在中間件中。

如果通過訂閱store的方式,由于Redux不能準確拿到哪一個數據放生了變化,因此只能通過臟檢查的方式。例如:

function createWatcher(mapState, callback) { 
 let previousValue = null
 return (store) => {
 store.subscribe(() => { const value = mapState(store.getState()) if (value !== previousValue) {
 callback(value)
 }
 previousValue = value
 })
 }
}const watcher = createWatcher(state => { 
 // ...}, () => { // ...})

watcher(store)

這個方法有兩個缺點,一是在數據很復雜且數據量比較大的時候會有效率上的問題;二是,如果mapState函數依賴上下文的話,就很難辦了。在react-redux中,connect函數中mapStateToProps的第二個參數是props,可以通過上層組件傳入props來獲得需要的上下文,但是這樣監聽者就變成了React的組件,會隨著組件的掛載和卸載被創建和銷毀,如果我們希望這個響應式和組件無關的話就有問題了。

另一種方式就是在中間件中監聽數據變化。得益于Redux的設計,我們通過監聽特定的事件(Action)就可以得到對應的數據變化。

const search = () => (dispatch, getState) => { 
 // ...}const middleware = ({ dispatch }) => next => action => { 
 switch action.type { case 'FOO_CHANGE': case 'BAR_CHANGE': { const nextState = next(action) // 在本次dispatch完成以后再去進行新的dispatch
 setTimeout(() => dispatch(search()), 0) return nextState
 } default: return next(action)
 }
}

這個方法能解決大多數的問題,但是在Redux中,中間件和reducer實際上隱式訂閱了所有的事件(Action),這顯然是有些不合理的,雖然在沒有性能問題的前提下是完全可以接受的。

面向對象的響應式

ECMASCRIPT 5.1引入了getter和setter,我們可以通過getter和setter實現一種響應式。

class Model { 
 _foo = ''
 get foo() { return this._foo
 }
 set foo(value) { this._foo = value this.search()
 }
 search() { // ...
 }
}// 當然如果沒有getter和setter的話也可以通過這種方式實現class Model { 
 foo = ''
 getFoo() { return this.foo
 }
 setFoo(value) { this.foo = value this.search()
 }
 search() { // ...
 }
}

Mobx和Vue就使用了這樣的方式實現響應式。當然,如果不考慮兼容性的話我們還可以使用Proxy。

當我們需要響應若干個值然后得到一個新值的話,在Mobx中我們可以這么做:

class Model { 
 @observable hour = '00'
 @observable minute = '00'
 @computed get time() { return `${this.hour}:${this.minute}`
 }
}

Mobx會在運行時收集time依賴了哪些值,并在這些值發生改變(觸發setter)的時候重新計算time的值,顯然要比EventEmitter的做法方便高效得多,相對Redux的middleware更直觀。

但是這里也有一個缺點,基于getter的computed屬性只能描述y = f(x)的情形,但是現實中很多情況f是一個異步函數,那么就會變成y = await f(x),對于這種情形getter就無法描述了。

對于這種情形,我們可以通過Mobx提供的autorun來實現:

class Model { 
 @observable keyword = ''
 @observable searchResult = [] constructor() {
 autorun(() => { // ajax ...
 })
 }
}

由于運行時的依賴收集過程完全是隱式的,這里經常會遇到一個問題就是收集到意外的依賴:

class Model { 
 @observable loading = false
 @observable keyword = ''
 @observable searchResult = [] constructor() {
 autorun(() => { if (this.loading) { return
 } // ajax ...
 })
 }
}

顯然這里loading不應該被搜索的autorun收集到,為了處理這個問題就會多出一些額外的代碼,而多余的代碼容易帶來犯錯的機會。 或者,我們也可以手動指定需要的字段,但是這種方式就不得不多出一些額外的操作:

class Model { 
 @observable loading = false
 @observable keyword = ''
 @observable searchResult = []
 disposers = []
 fetch = () => { // ...
 }
 dispose() { this.disposers.forEach(disposer => disposer())
 } constructor() { this.disposers.push(
 observe(this, 'loading', this.fetch),
 observe(this, 'keyword', this.fetch)
 )
 }
}class FooComponent extends Component { 
 this.mode = new Model()
 componentWillUnmount() { this.state.model.dispose()
 } // ...}

而當我們需要對時間軸做一些描述時,Mobx就有些力不從心了,例如需要延遲5秒再進行搜索。

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

前端響應式編程的方案及其缺點的詳細介紹(附代碼)

前端響應式編程的方案及其缺點的詳細介紹(附代碼):本篇文章給大家帶來的內容是關于前端響應式編程的方案及其缺點的詳細介紹(附代碼),有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。現實世界有很多是以響應式的方式運作的,例如我們會在收到他人的提問,然后做出響應,給出相應的回答。在
推薦度:
  • 熱門焦點

最新推薦

猜你喜歡

熱門推薦

專題
Top
主站蜘蛛池模板: 欧美中文日韩 | 亚洲欧美字幕 | 久久亚洲精选 | 欧美日韩国产综合在线 | 欧美日韩精品 | 国产日韩欧美在线观看不卡 | 久操精品在线观看 | 久久亚洲精品国产精品777777 | 欧美 日韩 亚洲另类专区 | 国产又大又粗又猛又爽的视频 | 国产不卡视频在线观看 | 免费的黄色毛片 | 福利毛片 | 日韩成人小视频 | 国产日韩精品欧美一区视频 | 亚洲精品视频在线观看免费 | 国产99久久九九精品免费 | 亚洲精品国产字幕久久vr | 国产精品色综合久久 | 好看的电影网站亚洲一区 | 国产第8页 | 精品久久久久中文字幕日本 | 亚洲欧美经典 | 成人精品视频在线观看 | 欧美极品欧美日韩 | 国产一区二区三区日韩欧美 | 国产一区二区日韩欧美在线 | julia一区| 亚洲欧美日韩一区 | 免费看特级淫片日本 | 久久国产亚洲欧美日韩精品 | 欧美激情在线精品一区二区 | 国精产品一区 | 国产欧美高清 | 亚洲国产精品成人综合久久久 | 国产精品第一区在线观看 | 99精品高清视频一区二区 | 91精品国产综合久久久久久 | 日韩a在线观看免费观看 | 日韩美一区二区 | 亚洲精品在线第一页 |