React項目實戰

前言

近期我在負責開發一個大型電商平臺項目,所採用的前端架構是React.js。設計到的技術棧有Reactjs、 React-Router、Redux、Nodejs、Webpack、Sass等等。這篇文章就以如今比較火的框架React.js來跟小夥伴們聊聊。css

就去年聊的水生火熱的三大框架(React、vue、angular)。在這裏我主要介紹的是Reactjs。分享給你們我近期開發的電商項目涉及到的知識點。若是你是準備近期着手學習Reactjs的,我能夠推薦給你一些學習方法。若是你已經玩React易如反掌了,咱們能夠一塊兒聊聊React,聊聊JavaScript。若是你是React專家級別的,老司機請帶帶我。廢話就很少說了。總之一句話,但願小夥伴能共同窗習,共同進步。下面進入正題;html

原理

在Web開發中,咱們總須要將變化的數據實時反應到UI上,這時就須要對DOM進行操做。而複雜或頻繁的DOM操做一般是性能瓶頸產生的緣由(如何進行高性能的複雜DOM操做一般是衡量一個前端開發人員技能的重要指標)。React爲此引入了虛擬DOM(Virtual DOM)的機制:在瀏覽器端用Javascript實現了一套DOM API。基於React進行開發時全部的DOM構造都是經過虛擬DOM進行,每當數據變化時,React都會從新構建整個DOM樹,而後React將當前整個DOM樹和上一次的DOM樹進行對比,獲得DOM結構的區別,而後僅僅將須要變化的部分進行實際的瀏覽器DOM更新。前端

並且React可以批處理虛擬DOM的刷新,在一個事件循環(Event Loop)內的兩次數據變化會被合併,例如你連續的先將節點內容從A變成B,而後又從B變成A,React會認爲UI不發生任何變化,而若是經過手動控制,這種邏輯一般是極其複雜的。儘管每一次都須要構造完整的虛擬DOM樹,可是由於虛擬DOM是內存數據,性能是極高的,而對實際DOM進行操做的僅僅是Diff部分,於是能達到提升性能的目的。這樣,在保證性能的同時,開發者將再也不須要關注某個數據的變化如何更新到一個或多個具體的DOM元素,而只須要關心在任意一個數據狀態下,整個界面是如何Render的。vue

若是你像在90年代那樣寫過服務器端Render的純Web頁面那麼應該知道,服務器端所要作的就是根據數據Render出HTML送到瀏覽器端。若是這時由於用戶的一個點擊須要改變某個狀態文字,那麼也是經過刷新整個頁面來完成的。服務器端並不須要知道是哪一小段HTML發生了變化,而只須要根據數據刷新整個頁面。換句話說,任何UI的變化都是經過總體刷新來完成的。而React將這種開發模式以高性能的方式帶到了前端,每作一點界面的更新,你均可以認爲刷新了整個頁面。至於如何進行局部更新以保證性能,則是React框架要完成的事情。node

借用Facebook介紹React的視頻中聊天應用的例子,當一條新的消息過來時,傳統開發的思路如上圖,你的開發過程須要知道哪條數據過來了,如何將新的DOM結點添加到當前DOM樹上;而基於React的開發思路以下圖,你永遠只須要關心數據總體,兩次數據之間的UI如何變化,則徹底交給框架去作。能夠看到,使用React大大下降了邏輯複雜性,意味着開發難度下降,可能產生Bug的機會也更少。react

React組件

組件屬性:
git

ReactJS是基於組件化的開發,React 容許將代碼封裝成組件(component),而後像插入普通 HTML 標籤同樣,在網頁中插入這個組件。算法

組件1redux

import React from 'react';

import CheckoutPurchasedHeader from '../../module/CheckoutPurchasedHeader' 

class OrderSkuList extends React.Component {
    constructor(props) {
        super(props); 
    }

    render(){
        let Header = ["商品信息","單價(元)","數量","小計(元)","操做"]
        return(
            <div className="order-detail-my-order">
                <CheckoutPurchasedHeader _Header={ Header } />
            </div>
        )
    }
}

export default OrderSkuList 
複製代碼

組件2瀏覽器

import React, { Component, PropTypes } from 'react';
    class CheckoutPurchasedHeader extends Component {
        constructor(props){
            super( props);
        }
        render() {
            let { _Header } = this.props;
            let nodes = [];
            if( _Header ){
                nodes = _Header.map( (data,index)=>{
                    return <li key={ index }>{data}</li>
            })
        }

           return (
                <ul className="checkout-purchased-header">
                    { nodes }
                </ul>
            );
        }
    }

    export default CheckoutPurchasedHeader;
複製代碼

看到這段代碼,有幾點須要注意:

  • 獲取屬性的值用的是this.props.屬性名。

  • 建立的組件名稱首字母必須大寫。

  • 爲元素添加css的class時,要用className。

  • 組件的style屬性的設置方式也值得注意,要寫成style={{width: this.state.witdh}}。

組件狀態:

組件免不了要與用戶互動,React 的一大創新,就是將組件當作是一個狀態機,一開始有一個初始狀態,而後用戶互動,致使狀態變化,從而觸發從新渲染 UI .

import React, { Component, PropTypes } from 'react';
    class CheckoutPurchasedHeader extends Component {
        constructor(props){
            super( props);
            this.state ={
                _Header: ["商品信息","單價(元)","數量","小計(元)","操做"]
            }
        }
        render() {
            let nodes = [];
            if( this.state._Header){
                nodes = this.state._Header.map( (data,index)=>{
                    return <li key={ index }>{data}</li>
            })
        }

           return (
                <ul className="checkout-purchased-header">
                    { nodes }
                </ul>
            );
        }
    }

    export default CheckoutPurchasedHeader;
複製代碼

這裏值得注意的幾點以下:

  • this.state初始化該組件所要用到的對象。

  • 訪問state的方法是this.state.屬性名。

  • 變量用{}包裹,不須要再加雙引號。

  • 能夠經過this.setState方法來修改當前組件的state。當檢測到state有變化的時候,組件會從新render.

組件的生命週期

組件的生命週期分紅三個狀態:

Mounting:已插入真實 DOM.

Updating:正在被從新渲染。

Unmounting:已移出真實 DOM.

React 爲每一個狀態都提供了兩種處理函數,will 函數在進入狀態以前調用,did 函數在進入狀態以後調用,三種狀態共計五種處理函數。

componentWillMount()

componentDidMount()

componentWillUpdate(object nextProps, object nextState)

componentDidUpdate(object prevProps, object prevState)

componentWillUnmount()

此外,React 還提供兩種特殊狀態的處理函數。

componentWillReceiveProps(object nextProps):已加載組件收到新的參數時調用。

shouldComponentUpdate(object nextProps, object nextState):組件判斷是否從新渲染時調用。

組件的嵌套

React是基於組件化的開發,那麼組件化開發最大的優勢是什麼?毫無疑問,固然是複用.仔細閱讀上面第1點的代碼,你會發現CheckoutPurchasedHeader組件能夠在任何地方複用。

爲何選擇React?

React最初開發這個特別的框架目標是「搭建數據須要頻繁更改的大型應用」。這也就能夠說是React項目搭建算是蠻複雜的。好比說寫一個簡單的helloworld。其餘的框架幾行代碼就解決,可是React寫起來就比較繁瑣。 但這也能夠說是React的優勢,代碼的組件化,會大大的提高後期開發跟維護的效率。說到這裏,我就要開始說說爲何咱們要選擇React.下面是我總結六點內容來闡述React的優點所在。

React效率極高
同構,純粹的JavaScript
Javascript庫(JSX)
一切都是component
單向數據流
Facebook

React的效率高只要體如今他的虛擬dom上

React.render(
<div className="commentBox">
  Hello, world! I am a CommentBox.
</div>  );
複製代碼

這裏的div其實和dom裏面的div徹底是兩碼事兒,只不過React提供了和DOM相似的Tag和API,事實上React會經過他本身的邏輯去轉化爲真正的DOM。因此,把這種叫作虛擬DOM.

那麼這樣作有什麼好處呢?最明顯的一點好處就是React所謂的 dom diff ,可以實現delta級別的dom更新。當有數據變更致使DOM變更時,React不是全局刷新,而是經過它內部的 dom diff 算法計算出不一樣點,而後以最小粒度進行更新。這也是React號稱性能好的緣由。

其次,還有一點很是好的地方就在於,有了虛擬DOM就可讓UI脫離設備,換句話說,只要有對應的轉化關係,如:虛擬DOM -> 瀏覽器DOM,就能進行渲染。

React 使用 JSX 來替代常規的 JavaScript

JSX 是一個看起來很像 XML 的 JavaScript 語法擴展。它有如下優勢:

JSX 執行更快,由於它在編譯爲 JavaScript 代碼後進行了優化。

它是類型安全的,在編譯過程當中就能發現錯誤。

使用 JSX 編寫模板更加簡單快速。

組件化

虛擬DOM(virtual-dom)不只帶來了簡單的UI開發邏輯,同時也帶來了組件化開發的思想,所謂組件,即封裝起來的具備獨立功能的UI部件。React推薦以組件的方式去從新思考UI構成,將UI上每個功能相對獨立的模塊定義成組件,而後將小的組件經過組合或者嵌套的方式構成大的組件,最終完成總體UI的構建。例如,Facebook的instagram.com整站都採用了React來開發,整個頁面就是一個大的組件,其中包含了嵌套的大量其它組件,你們有興趣能夠看下它背後的代碼。若是說MVC的思想讓你作到視圖-數據-控制器的分離,那麼組件化的思考方式則是帶來了UI功能模塊之間的分離。

React自己其實只是一個V,並非一個完整的框架

因此若是是大型應用想要一套完整的框架的話,react-router和redux是必不可少的。react的最大的問題就在於它組件跟組件之間的數據傳遞很麻煩,好比說父組件跟子組件公用同一個數據,子組件這時要修改數據的話,須要經過重重回調到父組件上,才能修改該數據,可是有了redux以後,全部的數據存放在頂層state樹上,每一個組件均可以公用頂層數據源的數據。組件經過觸發action來修改數據。

Facebook這條大腿支撐着React的開發迭代

在活躍度跟質量上天然是能夠有保障的。上述這些優勢也沒法判定react就是一個很完美的框架,但最起碼,它提出了一個全新的概念,新鮮的東西老是可以吸引你們的眼球。可是在架構選型上,得要根據實際應用的特色來選擇合適的框架。

談談心得 最後一段我想闡述一些我實際開發中的心得。我作前端開發說長不長,說短也有四年了。所說的有不對的地方望指出。在過去的兩年裏前端這個市場忽然火起來了,致使一會兒出來了不少的前端開發人員。需求多了,競爭天然而然的也就多了。那麼問題來了,咱們要怎樣去突出本身?我發表幾點我的意見。

不怕技術不成熟,關鍵是要用心。

不懂就問,要多溝通交流。不要讓技術有侷限性。

時常關注技術論壇。關注其餘人寫代碼的方式,從中領悟優缺點。

時常要關注新的技術。

做者:@leotao

相關文章
相關標籤/搜索