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

資訊專欄INFORMATION COLUMN

【React進(jìn)階系列】手寫redux api

Elle / 648人閱讀

摘要:每個(gè)接受的和函數(shù)作為命名參數(shù),并返回一個(gè)函數(shù)。調(diào)用鏈中最后一個(gè)會(huì)接受真實(shí)的的方法作為參數(shù),并借此結(jié)束調(diào)用鏈。

簡介: 手寫實(shí)現(xiàn)redux基礎(chǔ)api

createStore( )和store相關(guān)方法

api回顧:

createStore(reducer, [preloadedState], enhancer)

創(chuàng)建一個(gè) Redux store 來以存放應(yīng)用中所有的 state
reducer (Function): 接收兩個(gè)參數(shù),當(dāng)前的 state 樹/要處理的 action,返回新的 state 樹
preloadedState: 初始時(shí)的 state
enhancer (Function): store creator 的高階函數(shù),返回一個(gè)新的強(qiáng)化過的 store creator

Store 方法

getState() 返回應(yīng)用當(dāng)前的 state 樹
dispatch(action) 分發(fā) action。這是觸發(fā) state 變化的惟一途徑
subscribe(listener) 添加一個(gè)變化監(jiān)聽器。每當(dāng) dispatch action 的時(shí)候就會(huì)執(zhí)行,state 樹中的一部分可能已經(jīng)變化
replaceReducer(nextReducer) 替換 store 當(dāng)前用來計(jì)算 state 的 reducer(高級(jí)不常用,不作實(shí)現(xiàn))實(shí)現(xiàn) Redux 熱加載機(jī)制會(huì)用到

源碼實(shí)現(xiàn):

./self-redux.js

export function createStore(reducer, enhancer) {
  if(enhancer) {
     return enhancer(createStore)(reducer)
  }
  let currentState = {}
  let currentListeners = []
  function getState() {
    return currentState
  }
  function subscribe(listeners) {
    currentListeners.push(listener)
  }
  function dispatch(action) {
    currentState = reducer(currentState, action)
    currentListeners.forEach(v => v())
    return action
  }
  dispatch({ type: "@rainie/init-store" })
  return {
    getState,
    subscribe,
    dispatch
  }
}

demo:驗(yàn)證正確性

// import { createStore } from "redux"
// 將redux文件替換成自己實(shí)現(xiàn)的redux文件
   import { createStore } from "./self-redux.js"

// 這就是reducer處理函數(shù),參數(shù)是狀態(tài)和新的action
function counter(state=0, action) {
  // let state = state||0
  switch (action.type) {
    case "加機(jī)關(guān)槍":
      return state + 1
    case "減機(jī)關(guān)槍":
      return state - 1
    default:
      return 10
  }
}
// 新建store
const store = createStore(counter)
const init = store.getState()
console.log(`一開始有機(jī)槍${init}把`)
function listener(){
  const current = store.getState()
  console.log(`現(xiàn)在有機(jī)槍${current}把`)
}
// 訂閱,每次state修改,都會(huì)執(zhí)行l(wèi)istener
store.subscribe(listener)
// 提交狀態(tài)變更的申請(qǐng)
store.dispatch({ type: "加機(jī)關(guān)槍" })
combineReducers(reducers)

api簡介

把一個(gè)由多個(gè)不同 reducer 函數(shù)作為 value 的 object,合并成一個(gè)最終的 reducer 函數(shù)
實(shí)現(xiàn) Redux 熱加載機(jī)制會(huì)用到
import { combineReducers } from "redux"
import todos from "./todos"
import counter from "./counter"

export default combineReducers({
  todos,
  counter
})

實(shí)現(xiàn):

實(shí)質(zhì)就是返回一個(gè)大的function 接受state,action,然后根據(jù)key用不同的reducer
注:combinedReducer的key跟state的key一樣

const reducer = combineReducers({
  a: doSomethingWithA,
  b: processB,
  c: c
})
function reducer(state = {}, action) {
  return {
    a: doSomethingWithA(state.a, action),
    b: processB(state.b, action),
    c: c(state.c, action)
  }
}
function combindReducer(reducers) {
    // 第一個(gè)只是先過濾一遍 把非function的reducer過濾掉
  const reducerKeys = Object.keys(reducers)
  const finalReducers = {}
  reducerKeys.forEach((key) => {
      if(typeof reducers[key] === "function") {
      finalReducers[key] = reducers[key]
      } 
  })
  const finalReducersKeys = Object.keys(finalReducers)
    // 第二步比較重要 就是將所有reducer合在一起
    // 根據(jù)key調(diào)用每個(gè)reducer,將他們的值合并在一起
    let hasChange = false;
    const nextState = {};
    return function combind(state={}, action) {
        finalReducersKeys.forEach((key) => {
            const previousValue = state[key];
            const nextValue = reducers[key](previousValue, action);
            nextState[key] = nextValue;
            hasChange = hasChange || previousValue !== nextValue
        })
        return hasChange ? nextState : state;
    }
}

applyMiddleware(...middleware)

使用包含自定義功能的 middleware 來擴(kuò)展 Redux 是
...middleware (arguments): 遵循 Redux middleware API 的函數(shù)。
每個(gè) middleware 接受 Store 的 dispatch 和 getState 函數(shù)作為命名參數(shù),并返回一個(gè)函數(shù)。
該函數(shù)會(huì)被傳入 被稱為 next 的下一個(gè) middleware 的 dispatch 方法,并返回一個(gè)接收 action 的新函數(shù),這個(gè)函數(shù)可以直接調(diào)用 next(action),或者在其他需要的時(shí)刻調(diào)用,甚至根本不去調(diào)用它。
調(diào)用鏈中最后一個(gè) middleware 會(huì)接受真實(shí)的 store 的 dispatch 方法作為 next 參數(shù),并借此結(jié)束調(diào)用鏈。
所以,middleware 的函數(shù)簽名是 ({ getState, dispatch }) => next => action
import { createStore, combineReducers, applyMiddleware } from "redux"
import thunk from "redux-thunk"
import * as reducers from "./reducers"

let reducer = combineReducers(reducers)
// applyMiddleware 為 createStore 注入了 middleware:
let store = createStore(reducer, applyMiddleware(thunk))
中間件機(jī)制applyMiddleware的實(shí)現(xiàn)

中間件機(jī)制圖

實(shí)現(xiàn)步驟
1.擴(kuò)展createStore,使其接受第二個(gè)參數(shù)(中間件其實(shí)就是對(duì)createStore方法的一次擴(kuò)展)
2.實(shí)現(xiàn)applyMiddleware,對(duì)store的disptach進(jìn)行處理
3.實(shí)現(xiàn)一個(gè)中間件

正常調(diào)用

import React from "react"
import ReactDOM from "react-dom"
// import { createStore, applyMiddleware} from "redux"
import { createStore, applyMiddleware} from "./self-redux"
// import thunk from "redux-thunk"
import thunk from "./self-redux-thunk"
import { counter } from "./index.redux"
import { Provider } from "./self-react-redux";
import App from "./App"
 
const store = createStore(counter, applyMiddleware(thunk))
ReactDOM.render(
  (
    
      
    
  ),
  document.getElementById("root")) 
// 便于理解:函數(shù)柯利化例子
function add(x) {
  return function(y) {
    return x+y
  }
}
add(1)(2) //3

applymiddleware

// ehancer(createStore)(reducer)
// createStore(counter, applyMiddleware(thunk))
// applyMiddleware(thunk)(createStore)(reducer)
// 寫法函數(shù)柯利化
export function applyMiddleware(middleware) {
  return function (createStore) {
    return function(...args) {
      // ...
    }
  }
}


// 只處理一個(gè) middleware 時(shí)
export function applyMiddleware(middleware) {
   return createStore => (...args) => {
     const store = createStore(...args)
     let dispatch = store.dispatch

     const midApi = {
       getState: store.getState,
       dispatch: (...args) => dispatch(...args)
     }
    // 經(jīng)過中間件處理,返回新的dispatch覆蓋舊的
     dispatch = middleware(midApi)(store.dispatch)
    // 正常中間件調(diào)用:middleware(midApi)(store.dispatch)(action)

    return {
      ...store,
      dispatch
    }
   }
 }

// 處理多個(gè)middleware時(shí)

//  多個(gè) compose
 export function applyMiddleware(...middlewares) {
   return createStore => (...args) => {
     const store = createStore(...args)
     let dispatch = store.dispatch

     const midApi = {
       getState: store.getState,
       dispatch: (...args) => dispatch(...args)
     }

    const middlewareChain = middlewares.map(middleware => middleware(midApi))
    dispatch => compose(...middlewareChain(store.dispatch))
    //  dispatch = middleware(midApi)(store.dispatch)
    // middleware(midApi)(store.dispatch)(action)

    return {
      ...store,
      dispatch
    }
   }
 }

手寫redux-thunk異步中間件實(shí)現(xiàn)

// middleware(midApi)(store.dispatch)(action)
const thunk = ({ dispatch, getState }) => next => action => {
  // next就是store.dispatch函數(shù)
  // 如果是函數(shù),執(zhí)行以下,參數(shù)dispatch和getState
  if (typeof action == "function") {
    return action(dispatch, getState)
  }
  // 默認(rèn) 什么都不干
  return next(action)
}
export default thunk

處理異步action
export function addGunAsync() {
  // thunk插件作用,這里可以返回函數(shù)
  return dispatch => {
    setTimeout(() => {
      // 異步結(jié)束后,手動(dòng)執(zhí)行dispatch
      dispatch(addGun())
    }, 2000)
  }
}

趁熱打鐵,再實(shí)現(xiàn)一個(gè)中間件: dispatch接受一個(gè)數(shù)組,一次處理多個(gè)action

export arrayThunk = ({ dispatch, getState }) => next => action => {
  if(Array.isArray(action)) {
    return action.forEach(v => dispatch(v))
  }

  return next(action)
}

這類action會(huì)被處理
export function addTimes() {
  return [{ type: ADD_GUN },{ type: ADD_GUN },{ type: ADD_GUN }]
}
bindActionCreators的實(shí)現(xiàn)

在react-redux connect mapDispatchToProps中使用到了該方法,可以去看那篇blog,有詳解~

api: bindActionCreators(actionCreators, dispatch)

把 action creators 轉(zhuǎn)成擁有同名 keys 的對(duì)象,但使用 dispatch 把每個(gè) action creator 包圍起來,這樣可以直接調(diào)用它們

實(shí)現(xiàn):

 function bindActionCreator(creator, dispatch) {
   return (...args) => dispatch(creator(...args))
 }

 export function bindActionCreators(creators, dispatch) {
   let bound = {}
   Object.keys(creators).forEach( v => {
     let creator = creators[v]
     bound[v] = bindActionCreator(creator, dispatch)
   })
   return bound
 }
//  簡寫
 export function bindActionCreators(creators, dispatch) {
  return Object.keys(creators).reduce((ret, item) => {
     ret[item] =  bindActionCreator(creators[item], dispatch)
     return ret
   }, {})
 }
compose的實(shí)現(xiàn)

api: compose(...functions)

從右到左來組合多個(gè)函數(shù)。
當(dāng)需要把多個(gè) store 增強(qiáng)器 依次執(zhí)行的時(shí)候,需要用到它
import { createStore, applyMiddleware, compose } from "redux"
import thunk from "redux-thunk"
import DevTools from "./containers/DevTools"
import reducer from "../reducers"

const store = createStore(
  reducer,
  compose(
    applyMiddleware(thunk),
    DevTools.instrument()
  )
)

實(shí)現(xiàn):
compose(fn1, fn2, fn3)
fn1(fn2(fn3))

 export function compose(...funcs) {
   if(funcs.length == 0) {
     return arg => arg
   }
   if(funcs.length == 1) {
     return funcs[0]
   }
   return funcs.reduce((ret,item) => (...args) => ret(item(...args)))
 }

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

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

相關(guān)文章

  • React進(jìn)階系列手寫實(shí)現(xiàn)react-redux api

    簡介:簡單實(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
  • 前端進(jìn)階資源整理

    摘要:前端進(jìn)階進(jìn)階構(gòu)建項(xiàng)目一配置最佳實(shí)踐狀態(tài)管理之痛點(diǎn)分析與改良開發(fā)中所謂狀態(tài)淺析從時(shí)間旅行的烏托邦,看狀態(tài)管理的設(shè)計(jì)誤區(qū)使用更好地處理數(shù)據(jù)愛彼迎房源詳情頁中的性能優(yōu)化從零開始,在中構(gòu)建時(shí)間旅行式調(diào)試用輕松管理復(fù)雜狀態(tài)如何把業(yè)務(wù)邏輯這個(gè)故事講好和 前端進(jìn)階 webpack webpack進(jìn)階構(gòu)建項(xiàng)目(一) Webpack 4 配置最佳實(shí)踐 react Redux狀態(tài)管理之痛點(diǎn)、分析與...

    BlackMass 評(píng)論0 收藏0
  • 新上課程推薦:《React Hooks 案例詳解(React 進(jìn)階必備)》

    摘要:課程制作和案例制作都經(jīng)過精心編排。對(duì)于開發(fā)者意義重大,希望對(duì)有需要的開發(fā)者有所幫助。是從提案轉(zhuǎn)為正式加入的新特性。并不需要用繼承,而是推薦用嵌套。大型項(xiàng)目中模塊化與功能解耦困難。從而更加易于復(fù)用和獨(dú)立測試。但使用會(huì)減少這種幾率。 showImg(https://segmentfault.com/img/bVbpNRZ?w=1920&h=1080); 講師簡介 曾任職中軟軍隊(duì)事業(yè)部,參與...

    Lin_YT 評(píng)論0 收藏0
  • 2018大廠高級(jí)前端面試題匯總

    摘要:面試的公司分別是阿里網(wǎng)易滴滴今日頭條有贊挖財(cái)滬江餓了么攜程喜馬拉雅兌吧微醫(yī)寺庫寶寶樹海康威視蘑菇街酷家樂百分點(diǎn)和海風(fēng)教育。 (關(guān)注福利,關(guān)注本公眾號(hào)回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實(shí)戰(zhàn)、面試指導(dǎo)) 本人于7-8月開始準(zhǔn)備面試,過五關(guān)斬六將,最終抱得網(wǎng)易歸,深深感受到高級(jí)前端面試的套路。以下是自己整理的面試題匯總,不敢藏私,統(tǒng)統(tǒng)貢獻(xiàn)出來。 面試的公司分...

    zzir 評(píng)論0 收藏0

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

0條評(píng)論

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