react技術棧全家桶(總結及感悟)

簡介

react確實是一個神奇而優雅的框架。在從事react項目以前,一直是在作angular的,angular是一個全面和龐大的框架,在起初設計的時候什麼都有,複雜程度也很高,因此用angular作項目基本上不須要其餘的輔助庫來配合。可是react項目真的是不同了,要是隻會一個react的話,很難開發出需求的。由於react就只負責UI的渲染。javascript

這裏是我開發react工程的一個模板,平時開發過程當中遇到的需求上面都有對應的實例,技術棧:react + react-router + react-redux + saga + reselector + webpack + ES6 + Typescript + sass點擊這裏訪問css

作react項目須要掌握什麼

react 功能單一用於UI渲染, redux 用來管理數據, react-router 用來管理路由, webpack 用來配置工程, ES6 讓代碼更加優雅, redux-saga 用來處理異步請求, reselect 緩存機制用來減小state改變帶來的渲染壓力,還有一些爲了交互衍生出來的中間件 react-reduxreact-router-reduxreact-router-dom ,預處理器 SassLess 儘可能也掌握下。

react

前面有說過react只負責ui的渲染html

從V-dom出發

react最難能難得的就是虛擬dom的思想,這裏有個貼切的比喻:把dom和JavaScript想象爲各自的2個島嶼,中間有橋樑相連,可是橋上設有收費站,JavaScript去訪問dom島嶼的次數越多,費用就越高。這就是一個js操做dom的過程,也許咱們常常聽到或者看到說盡可能少的去操做dom,很耗性能。可是DOM 操做成本到底高在哪兒?,這邊小總結下:前端

從輸入uri到頁面加載好是一個很漫長的過程,咱們就從html的解析開始提及。①解析HTML,開始構建DOM樹;②解析CSS,生成CSS規則樹;③合併DOM樹和CSS規則樹,生成render樹;④佈局render樹(Layout/reflow),這時候負責元素尺寸大小,位置的計算,屬於js中迴流過程;⑤繪製render樹(paint),繪製頁面像素,屬於重繪的過程;⑥瀏覽器會將各層的信息發送給GPU(圖像處理器),GPU將各層合成(composite),顯示在屏幕上。這是初始化渲染的過程,經過js操做DOM後,會引發 迴流 和重繪,迴流的成本很高,一個節點的迴流會致使兄弟節點和子節點的迴流,這樣就一直在消耗GPU資源,因此纔有了成本高的說法。java

咱們從操做dom的成本開始引入react,它創造了虛擬dom而且將它們儲存起來,每當狀態發生變化的時候就會創造新的虛擬節點和之前的進行對比,讓變化的部分進行渲染。整個過程沒有對dom進行獲取和操做,只有等真正render時,纔會去操做真實dom,從而引起頁面的渲染。react

V-dom的缺點

ReactJS 使用虛擬 DOM 機制,讓前端開發者爲每一個組件提供一個 render 函數。render 函數把 props 和 state 轉換成 ReactJS 的虛擬 DOM,而後 ReactJS 框架根據render 返回的虛擬 DOM 建立相同結構的真實 DOM。webpack

每當 state 更改時,ReactJS 框架從新調用 render 函數,獲取新的虛擬 DOM 。而後,框架會比較上次生成的虛擬 DOM 和新的虛擬 DOM 有哪些差別,進而把差別應用到真實 DOM 上。git

這樣作有兩大缺點:es6

//每次 state 更改,render 函數都要生成完整的虛擬 DOM,哪怕 state 改動很小,
//render函數也會完整計算一遍。若是 render 函數很複雜,這個過程就會白白浪費不少計算資源。

//ReactJS 框架比較虛擬 DOM 差別的過程,既慢又容易出錯。好比,你想要在某個 <ul> 列表的頂部插入一項 <li> ,
//那麼 ReactJS 框架會誤覺得你修改了 <ul> 的每一項 <li>,而後在尾部插入了一個 <li>。
複製代碼

這是由於 ReactJS 收到的新舊兩個虛擬 DOM 之間相互獨立,ReactJS 並不知道數據源發生了什麼操做,只能根據新舊兩個虛擬 DOM 來猜想須要執行的操做。自動的猜想算法既不許又慢,必需要前端開發者手動提供 key 屬性、shouldComponentUpdate 方法、componentDidUpdate 方法或者 componentWillUpdate 等方法才能幫助 ReactJS 框架猜對。github

diff算法

react的diff算法用在什麼地方呢?當組件更新的時候,react會建立一個新的虛擬dom樹而且會和以前儲存的dom樹進行比較,這個比較的過程就用到了diff算法,因此組件初始化的時候是用不到的。react提出了一種假設,相同的節點具備相似的結構,而不一樣的節點具備不一樣的結構。在這種假設之上進行逐層的比較,若是發現對應的節點是不一樣的,那就直接刪除舊的節點以及它所包含的全部子節點而後替換成新的節點。若是是相同的節點,則只進行屬性的更改。

對於列表的diff算法稍有不一樣,由於列表一般具備相同的結構,在對列表節點進行刪除,插入,排序的時候,單個節點的總體操做遠比一個個對比一個個替換要好得多,因此在建立列表的時候須要設置key值,這樣react才能分清誰是誰。固然不寫key值也能夠,但這樣一般會報出警告,通知咱們加上key值以提升react的性能。

須要深刻了解diff源碼的請參考源碼解析

單項數據流

組件化

組件就是擁有獨立功能的視圖模塊,React的最大好處在於:功能組件化,遵照前端可維護的原則。

組件生命週期

組件初始化會觸發的5個鉤子函數

1.getDefaultProps()

設置默認的props,也能夠用defaultProps設置組件的默認屬性。

getDefaultProps至關於ES6中的 static defaultProps = {}

2.getInitialState()

在使用es6的class語法時是沒有這個鉤子函數的,能夠直接在constructor中定義this.state。此時能夠訪問this.props。

getInitialState至關於ES6 class中constructor的 this.state = {}

鉤子函數1 2 只有用React.createClass方法創造的組件類纔會發生做用,而且React.createClass已經被Fb官方廢棄,因此這裏不細講了。

3.componentWillMount()

組件初始化時只調用,之後組件更新不調用,整個生命週期只調用一次,此時能夠修改state。

4.render()

react最重要的步驟,建立虛擬dom,進行diff算法,更新dom樹都在此進行。

render() 應該是一個純函數,徹底根據state和props來決定返回結果,而不產生反作用,因此render中調用setState是錯的,由於純函數不該該引發狀態的改變

5.componentDidMount()

組件渲染以後調用,能夠經過this.getDOMNode()獲取和操做dom節點,只調用一次。

did的前綴表示進入狀態以後調用,好比componentDidMount,組件通常初始化都會在這裏進行數據請求。

爲何請求數據要在這個鉤子函數裏面調用?

個人總結詳見react中遇到的一些問題的解答

組件交互更新時觸發的5個鉤子函數

6.componentWillReceiveProps(nextProps)

組件初始化時不調用,組件接受新的props時調用。

開發過程當中通常是在這個鉤子函數裏面改變state,此方法中改變state不會二次渲染而是進行state合併。

7.shouldComponentUpdate(nextProps, nextState)

react性能優化很是重要的一環。組件接受新的state或者props時調用,咱們能夠設置在此對比先後兩個props和state是否相同,若是相同則返回false阻止更新,由於相同的屬性狀態必定會生成相同的dom樹,這樣就不須要創造新的dom樹和舊的dom樹進行diff算法對比,節省大量性能,尤爲是在dom結構複雜的時候。不過調用this.forceUpdate會跳過此步驟。

8.componentWillUpdate(nextProps, nextState)

組件初始化時不調用,只有在組件將要更新時才調用。

千萬不要在這個函數中調用this.setState()方法,會形成循環調用。

9.render()

同上render(),建立虛擬dom,進行diff算法,更新dom樹都在此進行。

10.componentDidUpdate()

組件初始化時不調用,組件更新完成後調用,此時能夠獲取dom節點。

在componentDidUpdate後才能獲取更新後的this.state。若是想獲取組件默認的props,而且賦值給State ,就能夠在這裏修改,達到UI上的效果。

組件卸載時調用

10.componentWillUnmount()

組件將要卸載時調用,一些事件監聽和定時器須要在此時清除,還有此組件store上面的值也能夠對應的清楚。

componentWillUnmount執行重置全部相關參數。在該方法中調用setState不會觸發render,由於全部的更新隊列,更新狀態都被重置爲null。

//數據清楚須要寫在reducer裏面
this.props.clearPointData();

[CLEAR_POINT_DATA]: (state, action: Action<any>) => {
    return Object.assign({}, state, {
        selectedReadingList: {},
        knowledgePoint: {},
    });
}
複製代碼

以上能夠看出來react總共有10個周期函數(render重複一次),這個10個函數能夠知足咱們全部對組件操做的需求,利用的好能夠提升開發效率和組件性能。

react-router

Router就是React的一個組件,它並不會被渲染,只是一個建立內部路由規則的配置對象,根據匹配的路由地址展示相應的組件。Route則對路由地址和組件進行綁定,Route具備嵌套功能,表示路由地址的包涵關係,這和組件之間的嵌套並無直接聯繫。Route能夠向綁定的組件傳遞7個屬性:children,history,location,params,route,routeParams,routes,每一個屬性都包涵路由的相關的信息。比較經常使用的有children(以路由的包涵關係爲區分的組件),location(包括地址,參數,地址切換方式,key值,hash值)。react-router提供Link標籤,這只是對a標籤的封裝,值得注意的是,點擊連接進行的跳轉並非默認的方式,react-router阻止了a標籤的默認行爲並用pushState進行hash值的轉變。切換頁面的過程是在點擊Link標籤或者後退前進按鈕時,會先發生url地址的轉變,Router監聽到地址的改變根據Route的path屬性匹配到對應的組件,將state值改爲對應的組件並調用setState觸發render函數從新渲染dom。

當頁面比較多時,項目就會變得愈來愈大,尤爲對於單頁面應用來講,初次渲染的速度就會很慢,這時候就須要按需加載,只有切換到頁面的時候纔去加載對應的js文件。react配合webpack進行按需加載的方法很簡單,Route的component改成getComponent,組件用require.ensure的方式獲取,並在webpack中配置chunkFilename。

const chooseProducts = (location, cb) => {
    require.ensure([], require => {
        cb(null, require('../Component/chooseProducts').default)
    },'chooseProducts')
}

const helpCenter = (location, cb) => {
    require.ensure([], require => {
        cb(null, require('../Component/helpCenter').default)
    },'helpCenter')
}

const saleRecord = (location, cb) => {
    require.ensure([], require => {
        cb(null, require('../Component/saleRecord').default)
    },'saleRecord')
}

const RouteConfig = (
    <Router history={history}>
        <Route path="/" component={Roots}>
            <IndexRoute component={index} />//首頁
            <Route path="index" component={index} />
            <Route path="helpCenter" getComponent={helpCenter} />//幫助中心
            <Route path="saleRecord" getComponent={saleRecord} />//銷售記錄
            <Redirect from='*' to='/'  />
        </Route>
    </Router>
);
複製代碼

react-router-redux

保持路由與應用狀態(state)同步。使用redux管理應用狀態(state),使用router管理路由,兩個庫不能協同工做,react-router-redux庫能夠協調這兩個庫。

react-router-dom

...

redux

組件間的通訊

react推崇的是單向數據流,自上而下進行數據的傳遞,可是由下而上或者不在一條數據流上的組件之間的通訊就會變的複雜。解決通訊問題的方法不少,若是隻是父子級關係,父級能夠將一個回調函數看成屬性傳遞給子級,子級能夠直接調用函數從而和父級通訊。

組件層級嵌套到比較深,可使用上下文getChildContext來傳遞信息,這樣在不須要將函數一層層往下傳,任何一層的子級均可以經過this.context直接訪問。

兄弟關係的組件之間沒法直接通訊,它們只能利用同一層的上級做爲中轉站。而若是兄弟組件都是最高層的組件,爲了可以讓它們進行通訊,必須在它們外層再套一層組件,這個外層的組件起着保存數據,傳遞信息的做用,這其實就是redux所作的事情。

組件之間的信息還能夠經過全局事件來傳遞。不一樣頁面能夠經過參數傳遞數據,下個頁面能夠用location.param來獲取。其實react自己很簡單,難的在於如何優雅高效的實現組件之間數據的交流。

redux

首先,redux並非必須的,它的做用至關於在頂層組件之上又加了一個組件,做用是進行邏輯運算、儲存數據和實現組件尤爲是頂層組件的通訊。若是組件之間的交流很少,邏輯不復雜,只是單純的進行視圖的渲染,這時候用回調,context就行,不必用redux,用了反而影響開發速度。可是若是組件交流特別頻繁,邏輯很複雜,那redux的優點就特別明顯了。我第一次作react項目的時候並無用redux,全部的邏輯都是在組件內部實現,當時爲了實現一個邏輯比較複雜的購物車,洋洋灑灑竟然寫了800多行代碼,回頭一看我本身都不知道寫的是啥,畫面太感人。

先簡單說一下redux和react是怎麼配合的。react-redux提供了connect和Provider兩個好基友,它們一個將組件與redux關聯起來,一個將store傳給組件。組件經過dispatch發出action,store根據action的type屬性調用對應的reducer並傳入state和這個action,reducer對state進行處理並返回一個新的state放入store,connect監聽到store發生變化,調用setState更新組件,此時組件的props也就跟着變化。

流程是這個樣子的:

值得注意的是connect,Provider,mapStateToProps,mapDispatchToProps是react-redux提供的,redux自己和react沒有半毛錢關係,它只是數據處理中心,沒有和react產生任何耦合,是react-redux讓它們聯繫在一塊兒。

接下來具體分析一下,redux以及react-redux究竟是怎麼實現的。

先上一張圖

明顯比第一張要複雜,其實兩張圖說的是同一件事。從上而下慢慢分析:

先說說redux

redux主要由三部分組成:store,reducer,action。

store是一個對象,它有四個主要的方法:

一、dispatch:

用於action的分發----在createStore中能夠用middleware中間件對dispatch進行改造,好比當action傳入dispatch會當即觸發reducer,有些時候咱們不但願它當即觸發,而是等待異步操做完成以後再觸發,這時候用redux-thunk對dispatch進行改造,之前只能傳入一個對象,改造完成後能夠傳入一個函數,在這個函數裏咱們手動dispatch一個action對象,這個過程是可控的,就實現了異步。

二、subscribe:

監聽state的變化----這個函數在store調用dispatch時會註冊一個listener監聽state變化,當咱們須要知道state是否變化時能夠調用,它返回一個函數,調用這個返回的函數能夠註銷監聽。 let unsubscribe = store.subscribe(() => {console.log('state發生了變化')})

三、getState:

獲取store中的state----當咱們用action觸發reducer改變了state時,須要再拿到新的state裏的數據,畢竟數據纔是咱們想要的。getState主要在兩個地方須要用到,一是在dispatch拿到action後store須要用它來獲取state裏的數據,並把這個數據傳給reducer,這個過程是自動執行的,二是在咱們利用subscribe監聽到state發生變化後調用它來獲取新的state數據,若是作到這一步,說明咱們已經成功了。

四、replaceReducer:

替換reducer,改變state修改的邏輯。

action:

action是一個對象,其中type屬性是必須的,同時能夠傳入一些數據。action能夠用actionCreactor進行創造。dispatch就是把action對象發送出去。

reducer:

reducer是一個函數,它接受一個state和一個action,根據action的type返回一個新的state。根據業務邏輯能夠分爲不少個reducer,而後經過combineReducers將它們合併,state樹中有不少對象,每一個state對象對應一個reducer,state對象的名字能夠在合併時定義。

像這個樣子:

const reducer = combineReducers({
     a: doSomethingWithA,
     b: processB,
     c: c
})
複製代碼

combineReducers:

其實它也是一個reducer,它接受整個state和一個action,而後將整個state拆分發送給對應的reducer進行處理,全部的reducer會收到相同的action,不過它們會根據action的type進行判斷,有這個type就進行處理而後返回新的state,沒有就返回默認值,而後這些分散的state又會整合在一塊兒返回一個新的state樹。

接下來分析一下總體的流程,首先調用store.dispatch將action做爲參數傳入,同時用getState獲取當前的狀態樹state並註冊subscribe的listener監聽state變化,再調用combineReducers並將獲取的state和action傳入。combineReducers會將傳入的state和action傳給全部reducer,並根據action的type返回新的state,觸發state樹的更新,咱們調用subscribe監聽到state發生變化後用getState獲取新的state數據。

redux的state和react的state二者徹底沒有關係,除了名字同樣。

上面分析了redux的主要功能,那麼react-redux到底作了什麼?

react-redux

若是隻使用redux,那麼流程是這樣的:

component --> dispatch(action) --> reducer --> subscribe --> getState --> component

用了react-redux以後流程是這樣的:

component --> actionCreator(data) --> reducer --> component

store的三大功能:dispatch,subscribe,getState都不須要手動來寫了。react-redux幫咱們作了這些,同時它提供了兩個好基友Provider和connect。

Provider是一個組件,它接受store做爲props,而後經過context往下傳,這樣react中任何組件均可以經過context獲取store。也就意味着咱們能夠在任何一個組件裏利用dispatch(action)來觸發reducer改變state,並用subscribe監聽state的變化,而後用getState獲取變化後的值。可是並不推薦這樣作,它會讓數據流變的混亂,過分的耦合也會影響組件的複用,維護起來也更麻煩。

connect --connect(mapStateToProps, mapDispatchToProps, mergeProps, options) 是一個函數,它接受四個參數而且再返回一個函數--wrapWithConnect,wrapWithConnect接受一個組件做爲參數wrapWithConnect(component),它內部定義一個新組件Connect(容器組件)並將傳入的組件(ui組件)做爲Connect的子組件而後return出去。

因此它的完整寫法是這樣的:connect(mapStateToProps, mapDispatchToProps, mergeProps, options)(component)

mapStateToProps(state, [ownProps]):

mapStateToProps 接受兩個參數,store的state和自定義的props,並返回一個新的對象,這個對象會做爲props的一部分傳入ui組件。咱們能夠根據組件所須要的數據自定義返回一個對象。ownProps的變化也會觸發mapStateToProps

function mapStateToProps(state) {
   return { todos: state.todos };
}
複製代碼

mapDispatchToProps(dispatch, [ownProps]):

mapDispatchToProps若是是對象,那麼會和store綁定做爲props的一部分傳入ui組件。若是是個函數,它接受兩個參數,bindActionCreators會將action和dispatch綁定並返回一個對象,這個對象會和ownProps一塊兒做爲props的一部分傳入ui組件。因此不論mapDispatchToProps是對象仍是函數,它最終都會返回一個對象,若是是函數,這個對象的key值是能夠自定義的

function mapDispatchToProps(dispatch) {
   return {
      todoActions: bindActionCreators(todoActionCreators, dispatch),
      counterActions: bindActionCreators(counterActionCreators, dispatch)
   };
}
複製代碼

mapDispatchToProps返回的對象其屬性其實就是一個個actionCreator,由於已經和dispatch綁定,因此當調用actionCreator時會當即發送action,而不用手動dispatch。ownProps的變化也會觸發mapDispatchToProps。

mergeProps(stateProps, dispatchProps, ownProps):

將mapStateToProps() 與 mapDispatchToProps()返回的對象和組件自身的props合併成新的props並傳入組件。默認返回 Object.assign({}, ownProps, stateProps, dispatchProps) 的結果。

options:

pure = true 表示Connect容器組件將在shouldComponentUpdate中對store的state和ownProps進行淺對比,判斷是否發生變化,優化性能。爲false則不對比。

其實connect函數並無作什麼,大部分的邏輯都是在它返回的wrapWithConnect函數內實現的,確切的說是在wrapWithConnect內定義的Connect組件裏實現的。

下面是一個完整的 react --> redux --> react 流程:

1、Provider組件接受redux的store做爲props,而後經過context往下傳。

2、connect函數在初始化的時候會將mapDispatchToProps對象綁定到store,若是mapDispatchToProps是函數則在Connect組件得到store後,根據傳入的store.dispatch和action經過bindActionCreators進行綁定,再將返回的對象綁定到store,connect函數會返回一個wrapWithConnect函數,同時wrapWithConnect會被調用且傳入一個ui組件,wrapWithConnect內部使用class Connect extends Component定義了一個Connect組件,傳入的ui組件就是Connect的子組件,而後Connect組件會經過context得到store,並經過store.getState得到完整的state對象,將state傳入mapStateToProps返回stateProps對象、mapDispatchToProps對象或mapDispatchToProps函數會返回一個dispatchProps對象,stateProps、dispatchProps以及Connect組件的props三者經過Object.assign(),或者mergeProps合併爲props傳入ui組件。而後在ComponentDidMount中調用store.subscribe,註冊了一個回調函數handleChange監聽state的變化。

3、此時ui組件就能夠在props中找到actionCreator,當咱們調用actionCreator時會自動調用dispatch,在dispatch中會調用getState獲取整個state,同時註冊一個listener監聽state的變化,store將得到的state和action傳給combineReducers,combineReducers會將state依據state的key值分別傳給子reducer,並將action傳給所有子reducer,reducer會被依次執行進行action.type的判斷,若是有則返回一個新的state,若是沒有則返回默認。combineReducers再次將子reducer返回的單個state進行合併成一個新的完整的state。此時state發生了變化。dispatch在state返回新的值以後會調用全部註冊的listener函數其中包括handleChange函數,handleChange函數內部首先調用getState獲取新的state值並對新舊兩個state進行淺對比,若是相同直接return,若是不一樣則調用mapStateToProps獲取stateProps並將新舊兩個stateProps進行淺對比,若是相同,直接return結束,不進行後續操做。若是不相同則調用this.setState()觸發Connect組件的更新,傳入ui組件,觸發ui組件的更新,此時ui組件得到新的props,react --> redux --> react 的一次流程結束。

上面的有點複雜,簡化版的流程是:

1、Provider組件接受redux的store做爲props,而後經過context往下傳。

2、connect函數收到Provider傳出的store,而後接受三個參數mapStateToProps,mapDispatchToProps和組件,並將state和actionCreator以props傳入組件,這時組件就能夠調用actionCreator函數來觸發reducer函數返回新的state,connect監聽到state變化調用setState更新組件並將新的state傳入組件。

connect能夠寫的很是簡潔,mapStateToProps,mapDispatchToProps只不過是傳入的回調函數,connect函數在必要的時候會調用它們,名字不是固定的,甚至能夠不寫名字。

簡化版本:

connect(state => state, action)(Component);
複製代碼

redux-saga

有待更新。。。

reselect

在React中最昂貴的操做就是渲染迴路.當組件檢測到輸入的變化,渲染迴路就會被觸發(譯註:這裏的意思的組件的action會改變redux的state,變回最終又回到組件了).

當咱們初次開始React程序的時候,咱們不會擔憂渲染迴路的花銷問題.可是當咱們的UI變得複雜的時候,咱們須要考慮這一點.React提供了一些工具讓咱們能劫持渲染迴路,若是渲染看上去沒必要要,咱們就可使用工具來阻止重渲染的發生.爲了這麼作,咱們要敲入componentShouldUpdate生命週期事件,返回一個布爾值,通知組件是否應該進行更新.這是以PureRenderMixin做爲基礎,它比較輸入的props和state和先前的props和state,若是二者相等就返回false.

不幸的是,僅此而已.

Reselect用來記憶selectors的庫.咱們定義的selectors是做爲函數獲取Redux state的某一部分.使用記憶能力,咱們能夠組織沒必要要的衍生數據的重渲染和計算過程,由此加速了咱們的app.

Reselect這個中間件要解決的問題是:在組件交互操做的時候,state發生變化的時候如何減小渲染的壓力.在Reselect中間中使用了緩存機制

"selector"是一個簡單的Redux庫

  • Selector能夠計算衍生的數據,可讓Redux作到存儲儘量少的state。
  • Selector比較高效,只有在某個參數發生變化的時候才發生計算過程.
  • Selector是能夠組合的,他們能夠做爲輸入,傳遞到其餘的selector.

參考

-使用Reselect改進React和Redux程序性能

ES6

在react工程當中,ES6/7/8處處可見,因此ES6也必需要掌握,由於內容太多就簡單總結下經常使用的一些技巧。具體的可參考 阮一峯老師的ES6入門

其實ES6相對於ES5來講,新增了不少的東西,列舉些經常使用的:使用let const徹底拋棄var;模板的導入導出(import,export);字符串的擴展(``,${});對象的擴展(結構賦值,新增了一些api如assgin(),keys(),is()等;數組的擴展(結構賦值,from(),of(),findIndex(),find()等);函數的擴展(函數參數能夠設置默認值,箭頭函數,沒有arguments對象等);經常使用來遍歷的(for of,forEach,for in,map等);用於解決異步的(generator函數,promise,async/await函數等);class和extends關鍵字等

雖然不少ES6的技巧用ES5一樣能實現,可是ES6大大提升了開發效率,代碼也更加優雅,何況各種的打包工具均可以將ES6轉化成適配低瀏覽器的ES5,因此推薦你們使用。

webpack

參考webpack官網

Sass or Less

隨着前端的不斷髮展,網站的頁面複雜度也在不斷提高,原生 CSS 已經讓開發者力不從心,預處理器賦予咱們的 "超能力"。淺談 CSS 預處理器:爲何要使用預處理器?

Sass

參考Sass語法

Less

參考Less語法

===================================end==================================

React Prepare

最後附上react技術棧的相關連接,但願對你們有幫助!

react

React 入門實例教程

React 技術棧系列教程

react 組件

React建立組件的三種方式及其區別

從性能角度看react組件拆分的重要性

react 性能篇

React性能優化總結

現代 Web 開發--React 篇

React.js 初學者應該知道的9件事

react router

React Router 使用教程

redux

Redux 入門教程(一):基本用法

Redux 入門教程(二):中間件與異步操做

Redux 入門教程(三):React-Redux 的用法

Redux 中文文檔

Redux 英文文檔

Redux 核心概念

React 實踐心得:react-redux 之 connect 方法詳解

redux-saga/redux-thunk

saga 中文文檔

聊一聊 redux 異步流之 redux-saga

Redux-Saga 實用指北

Reselect

Others

Flux 架構入門教程

Immutable

dom diff

Generator 函數的含義與用法

相關文章
相關標籤/搜索