React快速進階

上一篇文章,React入門 大體瞭解了, 如何基本的使用組件和更新組件. 如今,咱們來點新的~css

屬性驗證

React針對於props 專門提供了兩種屬性驗證, 來保證組件的可複用性~ propTypesdefaultProps. propTypes用來設置屬性是否必須, 類型等. defaultProps就是用來設置屬性的默認值.node

class Search extends Component {
    constructor(){
        super();
        this.number = 0;
    }
    render() {
        return(
            <div>
                <span>{this.props.children}</span>
            </div>
            )
    }
}
Search.propTypes = {
    children:PropTypes.string.isRequired
}
Search.defaultProps={
    children:"default value"
}

這裏,設置this.children屬性是必須的,而且若是你不寫的話, 他就會使用默認值,default value來替代. online demo
ok, 咱們來看一下, React提供了哪幾種PropType value.
from pro reactreact

proptypes

而且,在設置類型的同時,你還能夠在後面再寫上isRequired這樣的內容.PropTypes.array.isRequired.css3

還有一些其餘的內容, like:npm

proptype desc
oneOfType 能夠用來設置多種類型.PropTypes.oneOfType([PropTypes.string,PropTypes.number])
node 必須是可以渲染的類型,好比:numbers, strings, elements, or an array.
oneOf 只能是其中的某一個PropTypes.oneOf(['News', 'Photos'])

怎麼寫組件?

怎麼寫組件這個問題, 翻譯一下就是,怎麼使用state和props屬性. 由於組件的render和state以及props是息息相關的~
比較好的實踐是,state歸父UI管, props歸子UI管. 這裏, 咱們用一個簡單的demo來闡述一下. 寫一個搜索框~babel

基本樣式爲:app

search

這個demo其實就一箇中心點,經過onChange事件來控制內容信息的展現. 信息的展現,就是經過觸發this.setState 方法來完成.
我這裏, 就不貼代碼了,直接放在online demo裏了.ide

組件的生命週期

所謂的生命週期,實際上就是一些列觸發或者不觸發渲染的方法~
而涉及到這些渲染觸發操做的, 大概就有4個過程:性能

  • Mounting動畫

  • Unmounting

  • Props Change

  • State Change

咱們來講一下,每一個過程對應狀態的觸發順序.

Mounting

該過程表示渲染組件的過程. 簡而言之就是將咱們寫的組件類(class), 經過render 方法渲染到頁面上. 具體觸發順序是:

  • Class: 已經書寫好的UI 類

  • componentWillMount: 該方法會在render方法以前被invoke. 方法內部會設置好組件的state

  • render: 正式的觸發方法

  • componentDidMount: 將節點正式渲染到頁面上, 在該方法後面, 就能夠實際操做DOM.

Unmounting

卸載組件的過程. 即:

<div>
    <single></single>
</div>

渲染爲:

<div>
    {/* single component has been removed*/}
</div>

該過程實際上只會觸發一個方法:

  • componentWillUnmount: 在DOM即將刪除以前觸發該方法, 因此你能夠在該方法內部作一些事件的解綁

Props Change

看名字你們差很少已經猜出來了. 該過程就是主要處理props 內容的改變. 基本的過程爲:

  • ComponentWillReciveProps: 當組件接收到新的props便會觸發該方法. 若是你在該方法內調用this.setState其實是沒有效果的.(Ps: 該方法其實並無什麼x用)

  • shouldComponentUpdate: 檢測是否組件須要從新渲染. 實際上就是經過該方法決定, render 方法是否能夠直接跳過

  • componentWillUpdate: 新的props和state會被接收. 而且在該方法內不能使用this.setState進行渲染(反正也無效)

  • render: 不解釋了

  • componentDidUpdate: 在DOM已經徹底渲染完成後,觸發.

State Changes

狀態屬性的改變實際上和Props的流程差很少,只是是少了ComponentWillReciveProps方法.即,流程爲:

  • shouldComponentUpdate: 檢測是否組件須要從新渲染. 實際上就是經過該方法決定, render 方法是否能夠直接跳過

  • componentWillUpdate: 新的props和state會被接收. 而且在該方法內不能使用this.setState進行渲染(反正也無效)

  • render: 不解釋了

  • componentDidUpdate: 在DOM已經徹底渲染完成後,觸發.

lifecycle有什麼用

上面說了這麼多方法, 那這些方法究竟是寫在哪裏的呢?
~~ 只能寫在你的class UI中.
如今,咱們要在UI渲染完成時, 彈出一個提示框,說明完成。
so how to do?
很簡單.看一下代碼.

class Search extends Component{
    render(){
        return(
            <div>
            </div>
            )
    }
    componentDidMount(){
        alert('finish');
    }
}

這下, 應該懂了. 這裏大體瞭解一下就行, 當作鋪墊.

immutable state

由於state是起到組件渲染的關鍵做用. 因此, 通常外部的data都是存儲在state當中, 而這樣方式,即容易讓你不由自主的改動this.state中的屬性. 這樣很容易,形成你直接改動this.state狀態會無效, 以及會下降React內部對狀態渲染的性能.
因此, 建議就是,若是須要改動,請直接所有替換掉.
若是涉及到Object, 則可使用Object.assign 或者 filter,map等方法 copy一份.

let newObj = Object.assign({},this.state.male,this.state.female);
let newArray = this.state.people.map((val)=>val);

不過,因爲Object.assign支持度較低. 你能夠本身手動造一個輪子.

Object.prototype.assign=function(origin,target){
    for(var i in target){
        if(origin.hasOwnProperty(i)){
            origin[i]=target[i];
        }
    }
}

或者可使用import "babel-polyfill"來作替代. 不過,這還有一個問題,就是深淺copy. 這裏稍微提供點clue. 可使用 babel-polyfill 中的update方法, 該方法能夠像mongoDB同樣, 將更新事後的Object, deeply copy 一份給你. 這裏就不贅述了,到時候google 一下即差很少了.

動畫React

React爲了方便動畫開發, 特意提出了React CSSTransitionGroup這個addon. 細緻點來講, CSSTransitionGroup 只提供了3個效果-渲染, 新增,刪除. 並且每一個特效歸根結底,仍是須要你本身手動定義className, 他只是把className 的替換幫你作了.
so, 怎麼用?
首先得下載npm:

npm install --save react-addons-css-transition-group
// 在js中引用
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';

先看一個簡單的demo. 這裏也有線上demo:online demo

render(){
        let lis = this.state.num.map((i,index)=>(
                <li key={i} onClick={this.remove.bind(this,index)} >{i}</li>
            ));
        return(
            <ul>
                <CSSGroup transitionName="demo"
                        transitionEnterTimeout={300}
                        transitionLeaveTimeout={300}>
                {lis}
                </CSSGroup>
            </ul>
            )
    }

講真,React會在真正渲染的時候,在他應用的位置添加span元素 而後進行class的替換. 固然,若是涉及到更加複雜的動畫,就須要使用css3提供的transitionendanimationend來進行設置.
React一共提供了4個動畫狀態可供選擇:

  • Appear: 當第一次加載節點時,能夠進行的動畫.

    • transitionAppear: 表示是否開啓加載動畫. 默認狀況下是設置爲false. 因此,若是你要時候, 須要手動開啓transitionAppear={true}. 開啓以後, 你就須要添加.name-appearname-appear-active的class 動畫內容.

  • Enter: 當添加節點時,會觸發添加動畫.若是你使用的話,只須要設置.transitionEnterTimeout={timeout}便可。

    • transitionEnterTimeout: 用來設置節點添加動畫持續的時間,不過, 你一樣須要在class 中設置相同的transition時間. 若是時間不統一, 會以React設置爲主.和Appear同樣,也須要手動添加name-enter類名

  • Leave: 刪除節點時, 觸發的動畫. 同上 enter. 須要手動添加transitionLeaveTimeout

這裏提一下, 關於React class Name的設置位置. 只要和渲染節點設置在一塊兒便可.
好比,上面的demo, 個人scss就能夠設置爲:

li {
        font-size: 15px;
        line-height: 24px;
        list-style-position: inside;
        list-style-type: disc;
        text-align: left;
        width: 80%;
        border: 1px solid;
        margin-top: 8px;
        &.demo-leave {
            opacity: 1;
            transform: translateX(0);
            &.demo-leave-active {
                opacity: 0;
                transform: translateX(250px);
                transition: 0.3s;
            }
        }
    }
相關文章
相關標籤/搜索