国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

React-Redux進(jìn)階(像VUEX一樣使用Redux)

levius / 2609人閱讀

摘要:前言是一個(gè)非常實(shí)用的狀態(tài)管理庫(kù),對(duì)于大多數(shù)使用庫(kù)的開發(fā)者來(lái)說(shuō),都是會(huì)接觸到的。在使用享受其帶來(lái)的便利的同時(shí),我們也深受其問(wèn)題的困擾。只支持同步,讓狀態(tài)可預(yù)測(cè),方便測(cè)試。粗暴地級(jí)聯(lián)式刷新視圖使用優(yōu)化。

前言

Redux是一個(gè)非常實(shí)用的狀態(tài)管理庫(kù),對(duì)于大多數(shù)使用React庫(kù)的開發(fā)者來(lái)說(shuō),Redux都是會(huì)接觸到的。在使用Redux享受其帶來(lái)的便利的同時(shí), 我們也深受其問(wèn)題的困擾。

redux的問(wèn)題

之前在另外一篇文章Redux基礎(chǔ)中,就有提到以下這些問(wèn)題

純凈。Redux只支持同步,讓狀態(tài)可預(yù)測(cè),方便測(cè)試。 但不處理異步、副作用的情況,而把這個(gè)丟給了其他中間件,諸如redux-thunkredux-promiseredux-saga等等,選擇多也容易造成混亂~

啰嗦。那么寫過(guò)Redux的人,都知道actionreducer以及你的業(yè)務(wù)代碼非常啰嗦,模板代碼非常多。但是~,這也是為了讓數(shù)據(jù)的流動(dòng)清晰明了。

性能。粗暴地、級(jí)聯(lián)式刷新視圖(使用react-redux優(yōu)化)。

分型。原生 Redux-react 沒(méi)有分形結(jié)構(gòu),中心化 store

里面除了性能這一塊可以利用react-redux進(jìn)行優(yōu)化,其他的都是開發(fā)者不得不面對(duì)的問(wèn)題,對(duì)于代碼有潔癖的人,啰嗦這一點(diǎn)確實(shí)是無(wú)法忍受的。

方案目標(biāo)

如果你使用過(guò)VUEX的話, 那么對(duì)于它的API肯定會(huì)相對(duì)喜歡很多,當(dāng)然,vuex不是immutable,所以對(duì)于時(shí)間旅行這種業(yè)務(wù)不太友好。不過(guò),我們可以自己實(shí)現(xiàn)一個(gè)具有vuex的簡(jiǎn)潔語(yǔ)法和immutable屬性的redux-x(瞎命名)。

先看一下我們想要的目標(biāo)是什么樣的?
首先, 我們?cè)?/models里面定義每個(gè)子state樹,里面帶有namespace、state、reducers、effects等屬性, 如下:

export default {
  // 命名空間
  namespace: "common",
  // 初始化state
  state: {
    loading: false,
  },
  // reducers 同步更新 類似于vuex的mutations
  reducers: {
    updateLoadingStatus(state, action) {
      return {
        ...state,
        loading: action.payload
      }
    },
  },
  // reducers 異步更新 類似于vuex的actions
  efffects: {
    someEffect(action, store) {
      // some effect code
      ...
      ... 
      // 將結(jié)果返回
      return result
    }
  }
}

通過(guò)上面的實(shí)現(xiàn),我們基本解決了Redux本身的一些瑕疵

1.在effects中存放的方法用于解決不支持異步、副作用的問(wèn)題  

2.通過(guò)合并reducer和action, 將模板代碼大大減少  

3.具有分型結(jié)構(gòu)(namespace),并且中心化處理
如何實(shí)現(xiàn) 暴露的接口redux-x

首先,我們只是在外層封裝了一層API方便使用,那么說(shuō)到底,傳給redux的combineReducers還是一個(gè)redux對(duì)象。另外一個(gè)則是要處理副作用的話,那就必須使用到了中間件,所以最后我們暴露出來(lái)的函數(shù)的返回值應(yīng)該具有上面兩個(gè)屬性,如下:

import reduxSimp from "../utils/redux-simp" // 內(nèi)部實(shí)現(xiàn)
import common from "./common" // models文件下common的狀態(tài)管理
import user from "./user" // models文件下user的狀態(tài)管理
import rank from "./rank" // models文件下rank的狀態(tài)管理

const reduxX = reduxSimp({
  common,
  user,
  rank
})
export default reduxX
const store = createStore(
  combineReducers(reduxX.reducers),  // reducers樹
  {},
  applyMiddleware(reduxX.effectMiddler)  //  處理副作用中間件
)

第一步, 我們先實(shí)現(xiàn)一個(gè)暴露出來(lái)的函數(shù)reduxSimp,通過(guò)他對(duì)model里面各個(gè)屬性進(jìn)行加工,大概的代碼如下:

const reductionReducer = function() { // somecode }
const reductionEffects = function() { // somecode }
const effectMiddler = function() { // somecode }
/**
 * @param {Object} models
 */
const simplifyRedux = (models) => {
  // 初始化一個(gè)reducers 最后傳給combinReducer的值 也是最終還原的redux
  const reducers = {}
  // 遍歷傳入的model
  const modelArr = Object.keys(models)
  modelArr.forEach((key) => {
    const model = models[key]
    // 還原effect
    reductionEffects(model)
    // 還原reducer,同時(shí)通過(guò)namespace屬性處理命名空間
    const reducer = reductionReducer(model)
    reducers[model.namespace] = reducer
  })
  // 返回一個(gè)reducers和一個(gè)專門處理副作用的中間件
  return {
    reducers,
    effectMiddler
  }
}
還原effects

對(duì)于effects, 使用的時(shí)候如下(沒(méi)什么區(qū)別):

props.dispatch({
  type: "rank/fundRankingList_fetch",
  payload: {
    fundType: props.fundType,
    returnType: props.returnType,
    pageNo: fund.pageNo,
    pageSize: 20
  }
})

還原effects的思路大概就是先將每一個(gè)model下的effect收集起來(lái),同時(shí)加上命名空間作為前綴,將副作用的key即type 和相對(duì)應(yīng)的方法value分開存放在兩個(gè)數(shù)組里面,然后定義一個(gè)中間件,每當(dāng)有一個(gè)dispatch的時(shí)候,檢查key數(shù)組中是否有符合的key,如果有,則調(diào)用對(duì)應(yīng)的value數(shù)組里面的方法。

// 常量 分別存放副作用的key即type 和相對(duì)應(yīng)的方法
const effectsKey = []
const effectsMethodArr = []  
/**
 * 還原effects的函數(shù)
 * @param {Object} model
 */
const reductionEffects = (model) => {
  const {
    namespace,
    effects
  } = model
  const effectsArr = Object.keys(effects || {})

  effectsArr.forEach((effect) => {
    // 存放對(duì)應(yīng)effect的type和方法
    effectsKey.push(namespace + "/" + effect)
    effectsMethodArr.push(model.effects[effect])
  })
}

/**
 * 處理effect的中間件 具體參考redux中間件
 * @param {Object} store
 */
const effectMiddler = store => next => (action) => {
  next(action)
  // 如果存在對(duì)應(yīng)的effect, 調(diào)用其方法
  const index = effectsKey.indexOf(action.type)
  if (index > -1) {
    return effectsMethodArr[index](action, store)
  }
  return action
}
還原reducers

reducers的應(yīng)用也是和原來(lái)沒(méi)有區(qū)別:

props.dispatch({ type: "common/updateLoadingStatus", payload: true })

代碼實(shí)現(xiàn)的思路就是最后返回一個(gè)函數(shù),也就是我們通常寫的redux函數(shù),函數(shù)內(nèi)部遍歷對(duì)應(yīng)命名空間的reducer,找到匹配的reducer執(zhí)行后返回結(jié)果

/**
 * 還原reducer的函數(shù)
 * @param {Object} model 傳入的model對(duì)象
 */
const reductionReducer = (model) => {
  const {
    namespace,
    reducers
  } = model

  const initState = model.state
  const reducerArr = Object.keys(reducers || {})

  // 該函數(shù)即redux函數(shù)
  return (state = initState, action) => {
    let result = state
    reducerArr.forEach((reducer) => {
      // 返回匹配的action
      if (action.type === `${namespace}/${reducer}`) {
        result = model.reducers[reducer](state, action)
      }
    })
    return result
  }
}
最終代碼

最終的代碼如下,加上了一些錯(cuò)誤判斷:

// 常量 分別存放副作用的key即type 和相對(duì)應(yīng)的方法
const effectsKey = []
const effectsMethodArr = []

/**
 * 還原reducer的函數(shù)
 * @param {Object} model 傳入的model對(duì)象
 */
const reductionReducer = (model) => {
  if (typeof model !== "object") {
    throw Error("Model must be object!")
  }

  const {
    namespace,
    reducers
  } = model

  if (!namespace || typeof namespace !== "string") {
    throw Error(`The namespace must be a defined and non-empty string! It is ${namespace}`)
  }

  const initState = model.state
  const reducerArr = Object.keys(reducers || {})

  reducerArr.forEach((reducer) => {
    if (typeof model.reducers[reducer] !== "function") {
      throw Error(`The reducer must be a function! In ${namespace}`)
    }
  })

  // 該函數(shù)即redux函數(shù)
  return (state = initState, action) => {
    let result = state
    reducerArr.forEach((reducer) => {
      // 返回匹配的action
      if (action.type === `${namespace}/${reducer}`) {
        result = model.reducers[reducer](state, action)
      }
    })
    return result
  }
}

/**
 * 還原effects的函數(shù)
 * @param {Object} model
 */
const reductionEffects = (model) => {
  const {
    namespace,
    effects
  } = model
  const effectsArr = Object.keys(effects || {})

  effectsArr.forEach((effect) => {
    if (typeof model.effects[effect] !== "function") {
      throw Error(`The effect must be a function! In ${namespace}`)
    }
  })
  effectsArr.forEach((effect) => {
    // 存放對(duì)應(yīng)effect的type和方法
    effectsKey.push(namespace + "/" + effect)
    effectsMethodArr.push(model.effects[effect])
  })
}

/**
 * 處理effect的中間件 具體參考redux中間件
 * @param {Object} store
 */
const effectMiddler = store => next => (action) => {
  next(action)
  // 如果存在對(duì)應(yīng)的effect, 調(diào)用其方法
  const index = effectsKey.indexOf(action.type)
  if (index > -1) {
    return effectsMethodArr[index](action, store)
  }
  return action
}

/**
 * @param {Object} models
 */
const simplifyRedux = (models) => {
  if (typeof models !== "object") {
    throw Error("Models must be object!")
  }
  // 初始化一個(gè)reducers 最后傳給combinReducer的值 也是最終還原的redux
  const reducers = {}
  // 遍歷傳入的model
  const modelArr = Object.keys(models)
  modelArr.forEach((key) => {
    const model = models[key]
    // 還原effect
    reductionEffects(model)
    // 還原reducer,同時(shí)通過(guò)namespace屬性處理命名空間
    const reducer = reductionReducer(model)
    reducers[model.namespace] = reducer
  })
  // 返回一個(gè)reducers和一個(gè)專門處理副作用的中間件
  return {
    reducers,
    effectMiddler
  }
}

export default simplifyRedux
思考

如何結(jié)合Immutable.js使用?

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/101587.html

相關(guān)文章

  • Vuex、Flux、ReduxRedux-saga、Dva、MobX

    摘要:也就是說(shuō)不應(yīng)該有公開的,所有都應(yīng)該是私有的,只能有公開的。允許使用方法設(shè)置監(jiān)聽(tīng)函數(shù),一旦發(fā)生變化,就自動(dòng)執(zhí)行這個(gè)函數(shù)。用一個(gè)叫做的純函數(shù)來(lái)處理事件。可以通過(guò)得到當(dāng)前狀態(tài)。在中,同步的表現(xiàn)就是發(fā)出以后,立即算出。 這篇文章試著聊明白這一堆看起來(lái)挺復(fù)雜的東西。在聊之前,大家要始終記得一句話:一切前端概念,都是紙老虎。 不管是Vue,還是 React,都需要管理狀態(tài)(state),比如組件之...

    hiYoHoo 評(píng)論0 收藏0
  • 騷操作!在react中使用vuex

    摘要:原文地址前言筆者最近在學(xué)習(xí)使用,提到就繞不過(guò)去。同時(shí)應(yīng)當(dāng)注意,當(dāng)組件時(shí)應(yīng)當(dāng)重新收集依賴,因?yàn)橹笠蕾囮P(guān)系很可能已經(jīng)變化了清空依賴至此,我們的小目標(biāo)已經(jīng)完成了,在中使用不再是夢(mèng) 原文地址 前言 筆者最近在學(xué)習(xí)使用react,提到react就繞不過(guò)去redux。redux是一個(gè)狀態(tài)管理架構(gòu),被廣泛用于react項(xiàng)目中,但是redux并不是專為react而生,兩者還需要react-redux...

    OnlyLing 評(píng)論0 收藏0
  • 【React進(jìn)階系列】手寫實(shí)現(xiàn)react-redux api

    簡(jiǎn)介:簡(jiǎn)單實(shí)現(xiàn)react-redux基礎(chǔ)api react-redux api回顧 把store放在context里,所有子組件可以直接拿到store數(shù)據(jù) 使組件層級(jí)中的 connect() 方法都能夠獲得 Redux store 根組件應(yīng)該嵌套在 中 ReactDOM.render( , rootEl ) ReactDOM.render( ...

    劉玉平 評(píng)論0 收藏0
  • React-redux基礎(chǔ)

    摘要:簡(jiǎn)介創(chuàng)建的函數(shù),返回一個(gè)對(duì)象,包含等方法合并多個(gè)中間件處理,在實(shí)際的前調(diào)用一系列中間件,類似于綁定和函數(shù)式編程中常見(jiàn)的方法,介紹官方提供的綁定庫(kù)。 前言 在學(xué)習(xí)了React之后, 緊跟著而來(lái)的就是Redux了~ 在系統(tǒng)性的學(xué)習(xí)一個(gè)東西的時(shí)候, 了解其背景、設(shè)計(jì)以及解決了什么問(wèn)題都是非常必要的。接下來(lái)記錄的是, 我個(gè)人在學(xué)習(xí)Redux時(shí)的一些雜七雜八~ Redux是什么 通俗理解 h...

    jsyzchen 評(píng)論0 收藏0
  • React-redux進(jìn)階之Immutable.js

    摘要:的優(yōu)勢(shì)保證不可變每次通過(guò)操作的對(duì)象都會(huì)返回一個(gè)新的對(duì)象豐富的性能好通過(guò)字典樹對(duì)數(shù)據(jù)結(jié)構(gòu)的共享的問(wèn)題與原生交互不友好通過(guò)生成的對(duì)象在操作上與原生不同,如訪問(wèn)屬性,。 Immutable.js Immutable的優(yōu)勢(shì) 1. 保證不可變(每次通過(guò)Immutable.js操作的對(duì)象都會(huì)返回一個(gè)新的對(duì)象) 2. 豐富的API 3. 性能好 (通過(guò)字典樹對(duì)數(shù)據(jù)結(jié)構(gòu)的共享) Immutab...

    孫淑建 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<