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

資訊專欄INFORMATION COLUMN

深入redux技術(shù)棧

VPointer / 1555人閱讀

摘要:另外,內(nèi)置的函數(shù)在經(jīng)過一系列校驗后,觸發(fā),之后被更改,之后依次調(diào)用監(jiān)聽,完成整個狀態(tài)樹的更新。總而言之,遵守這套規(guī)范并不是強制性的,但是項目一旦稍微復(fù)雜一些,這樣做的好處就可以充分彰顯出來。

這一篇是接上一篇“react進(jìn)階漫談”的第二篇,這一篇主要分析redux的思想和應(yīng)用,同樣參考了網(wǎng)絡(luò)上的大量資料,但代碼同樣都是自己嘗試實踐所得,在這里分享出來,僅供一起學(xué)習(xí)(上一篇地址:個人博客/segmentFault)

注:本文中的所有示例代碼,已經(jīng)合成一個小的demo放在了這里,如果你認(rèn)為這個demo對你的學(xué)習(xí)起到了一點幫助,請給star以支持。

redux 簡介

本文默認(rèn)大家掌握一些react和flux架構(gòu)的相關(guān)知識,也用過或者了解過redux,所以并不會從最基礎(chǔ)的講起,而是直接對redux進(jìn)行總結(jié)。如果沒有用過redux,最好可以先看這里

想要理解redux,我們首先要總結(jié)redux的一些設(shè)計原則:

單一數(shù)據(jù)源

Redux中只有用單一個對象大樹結(jié)構(gòu)來的存儲整個應(yīng)用的狀態(tài),也就是整個應(yīng)用中會用到的數(shù)據(jù),稱之為store(存儲)。store除了存儲的數(shù)據(jù),還可以存儲整個應(yīng)用的狀態(tài)(包括router狀態(tài),后文有介紹),所以,通過store,實現(xiàn)一個對整個應(yīng)用的即時保存功能(建立快照)變?yōu)榭赡埽硗膺@種設(shè)計也為服務(wù)端渲染提供了可能。

狀態(tài)是只讀的

這一點符合flux的設(shè)計理念,我們并不能在components里面更改store的狀態(tài)(實際上redux會根據(jù)reducer生成store),而是只能通過dispatch,觸發(fā)action對當(dāng)前狀態(tài)進(jìn)行迭代,這里我們也并沒有直接修改應(yīng)用的狀態(tài),而是返回了一份全新的狀態(tài)。

狀態(tài)修改均由純函數(shù)構(gòu)成

Redux中的reducer的原型會長得像下面這樣,你可以把它當(dāng)作就是 之前的狀態(tài) + 動作 = 新的狀態(tài) 的公式:

(previousState, action) => newState

每一個reducer都是純函數(shù),這意味著它沒有任何副作用,這種設(shè)計的好處不僅在于用reducer對狀態(tài)修改變的簡單,純粹可以測試,另外,redux可以保存各個返回狀態(tài)從而方便地生成時間旅行,跟蹤每一次因為出發(fā)action而導(dǎo)致變更的結(jié)果。

我們?nèi)绻趓eact中使用redux,同時需要react-redux 和 redux。

redux 架構(gòu)與源碼分析

這一部分主要談一點自己的理解,可能有些抽象,也可能不完全正確,可直接跳過。

createStore

redux中核心的方法是createStore,react的核心功能全都覆蓋在createStore和其最終生成的store中,createStore方法本身支持傳入reducer、initialState、enhancer三參數(shù),enhancer可以作為增強的包裝函數(shù),這個我們并不是十分常用。

這個函數(shù)內(nèi)部維護(hù)了一個currentState,并且這個currentState可以通過getState函數(shù)(內(nèi)置)返回,另外本身實際上是實現(xiàn)了一個發(fā)布-訂閱模式,通過store.subscribe來訂閱事件,這個工作由react-redux來幫助我們隱式完成,這是為了在有dispatch的時候觸發(fā)所有監(jiān)聽從而更新整個狀態(tài)樹。另外,內(nèi)置的dispatch函數(shù)在經(jīng)過一系列校驗后,觸發(fā)reducer,之后state被更改,之后依次調(diào)用監(jiān)聽,完成整個狀態(tài)樹的更新。

middleWare

用過redux的朋友實際上都對于redux-thunk等中間件并不陌生,實際上很多時候這是不可缺少的,redux對middleWare也有很好的支持,這種理念我認(rèn)為和nodejs的中間件機(jī)制有些類似:action依次經(jīng)過各個middleWare然后傳給下一個,每一個middleWare也可以進(jìn)行另外的操作比如中斷或者改變action,知道最終的處理函數(shù)交給reducer。

redux的applyMiddleware函數(shù)非常精煉:

export default function applyMiddleware(...middlewares) {
  return (createStore) => (reducer, preloadedState, enhancer) => {
    var store = createStore(reducer, preloadedState, enhancer)
    var dispatch = store.dispatch
    var chain = []

    var middlewareAPI = {
      getState: store.getState,
      dispatch: (action) => dispatch(action)
      //注意這里的dispatch并不是一開始的store.dispatch,實際上是變化了的
    }
    chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }
}

核心是dispatch = compose(...chain)(store.dispatch),這句話是對于各個中間件的鏈?zhǔn)秸{(diào)用,其中compose的源代碼:

export default function compose(...funcs) {
  if (funcs.length === 0) {
    return arg => arg
  }

  if (funcs.length === 1) {
    return funcs[0]
  }

  const last = funcs[funcs.length - 1]
  const rest = funcs.slice(0, -1)
  return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args))
}

調(diào)用上一個函數(shù)的執(zhí)行結(jié)果給下一個函數(shù)。

實際上我們要寫一個middleware的過程也非常簡單,比如redux-trunk實際上就這點內(nèi)容:

function createThunkMiddleware(extraArgument) {
  return ({ dispatch, getState }) => next => action => {
    if (typeof action === "function") {
      return action(dispatch, getState, extraArgument);
    }

    return next(action);
  };
}

const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;

export default thunk;
redux 與路由

當(dāng)然,我們首先聲明react工具集的react-router并不一定必須搭配redux使用,只是redux另外有一個react-router-redux可以搭配react-router以及redux使用,效果非常好。

因為我們這部分并不是介紹react-router怎么使用的,關(guān)于react-router的用法請參考中文文檔。

react-router的特性

允許開發(fā)者通過JSX標(biāo)簽來聲明路由,這一點讓我們路由寫起來十分友好,并且聲明式路由的表述能力比較強。

嵌套路由以及路由匹配:可以在指定的path中傳遞參數(shù):

另外如果參數(shù)是可選的,我們通過括號包起來即可(:可選參數(shù))。

支持多種路由切換方式:我們知道現(xiàn)在的路由切換方式無外乎使用hashchange和pushState,前者有比較好的瀏覽器兼容性,但是卻并不像一個真正的url,而后者給我們提供優(yōu)雅的url體驗,但是卻需要服務(wù)端解決任意路徑刷新的問題(服務(wù)端要自動重定向到首頁)。

為什么需要react-router-redux

簡單的說,react-router-redux讓我們可以把路由也當(dāng)作狀態(tài)的一部分,并且可以使用redux的方式改變路由:直接調(diào)用dispatch:this.props.push(“/detail/”);,這樣把路由也當(dāng)作一個全局狀態(tài),路由狀態(tài)也是應(yīng)用狀態(tài)的一部分,這樣可能更有利于前端狀態(tài)管理。

react-router-redux是需要配合react-router來使用的,并不能多帶帶使用,在原本的項目中添加上react-router-redux也不復(fù)雜:

import { createStore, combineReducers, compose, applyMiddleware } from "redux";
import { routerReducer, routerMiddleware } from "react-router-redux";
import { hashHistory } from "react-router";

import ThunkMiddleware from "redux-thunk";
import rootReducer from "./reducers";
import DevTools from "./DevTools";

const finalCreateStore = compose(
  applyMiddleware(ThunkMiddleware,routerMiddleware(hashHistory)),
  DevTools.instrument()
)(createStore);

console.log("rootReducer",rootReducer);

const reducer = combineReducers({
  rootReducer,
  routing: routerReducer,
});

export default function configureStore(initialState) {
  const store = finalCreateStore(reducer, initialState);
  return store;
}

另外,上文提到的demoreact-router-redux-demo用了react-routerreact-router-redux,當(dāng)然也用到了redux的一些別的比較好的工作,比如redux-devtools,有興趣的朋友可以點擊這里

redux 與組件

這一部分講述的是一種組件書寫規(guī)范,并不是一些庫或者架構(gòu),這些規(guī)范有利于我們在復(fù)雜的項目中組織頁面,不至于混亂。

從布局的角度看,redux強調(diào)了三種不同的布局組件,Layouts,Views,Components:

Layouts: 指的是頁面布局組件,描述了頁面的基本結(jié)構(gòu),可以是無狀態(tài)函數(shù),一般就直接設(shè)置在最外層router的component參數(shù)中,并不承擔(dān)和redux直接交互的功能。比如我項目中的Layouts組件:

const Frame = (props) =>
       
{props.children}
;

Views組件,我認(rèn)為這個組件是Components的高階組件或者Components group,這一層是可以和redux進(jìn)行交互并且處理數(shù)據(jù)的,我們可以將一個整體性功能的組件組放在一個Views下面(注:由于我給出的demo十分簡單,因此Views層和Components層分的不是那么開)

Components組件,這是末級渲染組件,一般來說,這一層級的組件的數(shù)據(jù)通過props傳入,不直接和redux單向數(shù)據(jù)流產(chǎn)生交互,可以是木偶般的無狀態(tài)組件,或者是包含自身少量交互和狀態(tài)的組件,這一層級的組件可以被大量復(fù)用。

總而言之,遵守這套規(guī)范并不是強制性的,但是項目一旦稍微復(fù)雜一些,這樣做的好處就可以充分彰顯出來。

redux 與表單

redux的單向數(shù)據(jù)流相對于雙向數(shù)據(jù)綁定,在處理表單等問題上的確有點力不從心,但是幸運的是已經(jīng)開源了有幾個比較不錯的插件:

redux-form-utils,好吧,這個插件的star數(shù)目非常少,但是他比較簡單,源代碼也比較短,只有200多行,所以這是一個值得我們看源碼學(xué)習(xí)的插件(它的源碼結(jié)構(gòu)也非常簡單,就是先定一個一個高階組件,這個高階組件可以給我們自己定義的表單組件傳入新的props,定制組件,后一部分就是定義了一些action和reducer,負(fù)責(zé)在內(nèi)容變化的時候通知改變狀態(tài)樹),但是缺憾就是這個插件沒有對表單驗證做工作,所以如果我們需要表單驗證,還是需要自己做一些工作的。

另外還有一地方,這個插件源代碼寫法中用到了::這種ES6的語法,這其實是一種在es6中class內(nèi)部,使用babel-preset-stage-0即可使用的語法糖:::this.[functionName] 等價于 this.[functionName].bind(this, args?)

redux-form,這個插件功能復(fù)雜,代碼完善,體量也非常龐大,可以參考文檔進(jìn)行使用,但是讀懂源代碼就是比較麻煩的事情了。不過這個插件需要在redux的應(yīng)用的state下掛載一個節(jié)點,這個節(jié)點是不需要開發(fā)者自己來操控的,他唯一需要做的事情就是寫一個submit函數(shù)即可。我在自己的demo中也把一個例子稍加改動搬了過來,感覺用起來比較舒服。

redux 性能優(yōu)化

想要做到redux性能優(yōu)化,我們首先就要知道redux的性能可能會在哪些地方受到影響,否則沒有目標(biāo)是沒有辦法性能優(yōu)化的。

因為我也不是使用redux的老手,所以也并不能覆蓋所有性能優(yōu)化的點,我總結(jié)兩點:

有的時候,我們需要的數(shù)據(jù)格式會自帶冗余,可以抽取出一些公共的部分從而縮減大小,比如我們需要的數(shù)據(jù)格式可能是這樣的:

[
    {
        name:"Nike",
        title:"國家一級運動員","國家一級裁判員"
    }
    {
        name:"Jenny",
        title:"國家一級裁判員"
    }
    {
        name:"Mark",
        title:"國家一級運動員"
    }
]

這個時候?qū)嶋H上我們可以優(yōu)化成這樣:

[
    {
    "國家一級運動員":"Nike","Mark"
    "國家一級裁判員":"Jenny","Nike"
    }
]

這個時候,我們可以直接把后者當(dāng)作store的格式,而我們用reselect這個庫再轉(zhuǎn)變成我們所要的格式,關(guān)于reselect怎么用上述鏈接有更詳細(xì)的例子,在這里我就不過多介紹了。

事實上,對于redux來說,每當(dāng)store發(fā)生改變的時候,所有的connect都會重新計算,在一個大型應(yīng)用中,浪費的時間可想而知,為了減少性能浪費,我們可以對connect中的selector做緩存。

上文提到的reselect庫自帶了緩存特性,我們可以通過比較參數(shù)來確定是否使用緩存,這里用了純函數(shù)的特性。

reselect的緩存函數(shù)可以用戶自定義,具體可以參考上文github鏈接的readme。

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

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

相關(guān)文章

  • 深入redux技術(shù)

    摘要:另外,內(nèi)置的函數(shù)在經(jīng)過一系列校驗后,觸發(fā),之后被更改,之后依次調(diào)用監(jiān)聽,完成整個狀態(tài)樹的更新。總而言之,遵守這套規(guī)范并不是強制性的,但是項目一旦稍微復(fù)雜一些,這樣做的好處就可以充分彰顯出來。 這一篇是接上一篇react進(jìn)階漫談的第二篇,這一篇主要分析redux的思想和應(yīng)用,同樣參考了網(wǎng)絡(luò)上的大量資料,但代碼同樣都是自己嘗試實踐所得,在這里分享出來,僅供一起學(xué)習(xí)(上一篇地址:個人博客/s...

    imingyu 評論0 收藏0
  • 前端每周清單半年盤點之 React 與 ReactNative 篇

    摘要:前端每周清單半年盤點之與篇前端每周清單專注前端領(lǐng)域內(nèi)容,以對外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點分為新聞熱點開發(fā)教程工程實踐深度閱讀開源項目巔峰人生等欄目。與求同存異近日,宣布將的構(gòu)建工具由遷移到,引發(fā)了很多開發(fā)者的討論。 前端每周清單半年盤點之 React 與 ReactNative 篇 前端每周清單專注前端領(lǐng)域內(nèi)容,以對外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點;分為...

    Barry_Ng 評論0 收藏0
  • 解析Twitter前端架構(gòu) 學(xué)習(xí)復(fù)雜場景數(shù)據(jù)設(shè)計

    摘要:總結(jié)本文分析了在采用架構(gòu)下的數(shù)據(jù)設(shè)計結(jié)構(gòu),在一個復(fù)雜的場景下,希望引起讀者對能有一個更深入的認(rèn)識。 前幾天刷Twitter,發(fā)現(xiàn)Nicolas(Engineering at @twitter. Technical Lead for Twitter Lite)發(fā)布了這么一條推文: showImg(https://segmentfault.com/img/remote/1460000009...

    csRyan 評論0 收藏0
  • 干貨 | React技術(shù)耕耘 —— Redux

    摘要:作者小滬江前端開發(fā)工程師本文為原創(chuàng)文章,有不當(dāng)之處歡迎指出。于是,單一數(shù)據(jù)源規(guī)則實施起來,是規(guī)定用的頂層容器組件的來存儲單一對象樹,同時交給來管理。顧名思義,當(dāng)更新時,的回調(diào)函數(shù)會更新視圖層,以達(dá)到訂閱的效果。 作者:小boy (滬江web前端開發(fā)工程師)本文為原創(chuàng)文章,有不當(dāng)之處歡迎指出。轉(zhuǎn)載請注明出處。文章示例代碼:https://github.com/ikcamp/rea... ...

    LdhAndroid 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<