React

React簡介

FeceBook開源的一套框架,專一於MVC的視圖V模塊。實質是對V視圖的一種實現。javascript

React框架的設計沒有過度依賴於某個環境,它自建一套環境,就是virtual DOM(虛擬DOM)。html

提供基礎API:建立元素,渲染元素。前端

React的獨特之處:java

組件的組合模式單向數據流的設計(Date Flow)高效的性能(Virtual DOM)分離的設計react

React的核心思想:封裝組件,各個組件維護本身的狀態和 UI, 當狀態變動,自動從新渲染整個組件。git

瀏覽器環境中渲染github

<script src="lib/react.js" type="text/javascript" charset="utf-8"></script>
<script src="lib/react-dom.js" type="text/javascript" charset="utf-8"></script>

react.js: 構建虛擬DOM, React.createElement(); React核心庫,在應用中必須先加載核心庫。
react-dom.js: 將虛擬DOM渲染頁面中,ReactDOM.render(); DOM渲染器,React將核心庫和渲染器分離,目的:在Web頁面中顯示開發的組件。設計模式

JSX

JSX是React自定義的語法,最終JSX會轉化爲JS運行與頁面當中數組

組件

組件是React中核心概念,頁面當中的全部元素都經過React組件來表達,將要寫的React代碼絕大部分都是在作React組件的開發。瀏覽器

組合模式: 組合模式又稱之爲:部分-總體模式。使樹形結構的問題中,模式了簡單元素和複雜元素的概念,客戶程序能夠向處理簡單元素同樣來處理複雜的元素,從而使得客戶程序與複雜元素的內部結構解耦。

不管是應用等級仍是一個表單亦或是一個按鈕,都視爲一個組件。而後基於組件的組合構建整個應用。

clipboard.png

組合模式優勢:

  • 構建能夠重用的組件:組件的開發可以造成公司的組件,每一個業務的開發都能積累課重用的組件。

  • JSX語法

  • 具備彈性的架構: 可以構建簡單的頁面也能構建大型的前端應用。

  • 維護性高。

VIRTUAL DOM

React抽象出來的虛擬DOM樹,虛擬樹是React高性能的關鍵。(讓須要改變的元素纔去從新渲染)

單項數據流

單項數據流:one-way reactive data flow

React應用的核心設計模式,數據流向自頂向下。

頁面的UI和數據的對應是惟一的。

基礎API

createElement

React.createElement();

建立虛擬DOM

參數1:元素名稱, 例如: div,p, h1
參數2:屬性集合,例如:title,calssName,id,style
從參數3開始,表示該元素的子元素,一般這些元素經過createElement();建立, (文本文件能夠直接插入)

let ul = React.createElement('ul', {
    
    'title': '嘻嘻哈哈'
    
},'這是');

render

ReactDOM.render();
DOM渲染器,將元素渲染到頁面中。

參數1:虛擬DOM元素
參數2:HTML的容器元素。

ReactDOM.render(ul, document.querySelector('.app'));

示例:

<script src="lib/react.js" type="text/javascript" charset="utf-8"></script>
<script src="lib/react-dom.js" type="text/javascript" charset="utf-8"></script>


<script type="text/javascript">
    
    'use strict';
    
    let ul = React.createElement('ul', {
        
        'title': '嘻嘻哈哈'
        
    },'這是');
    
    
    ReactDOM.render(ul, document.querySelector('.app'));
    
</script>

crateClass

React.createClass();
定義組件

參數:配置對象。
對象中能夠添加任何方法,但一些屬性,方法是特殊的。

render: 組件中渲染輸出的虛擬DOM元素。

// component
let Uls = React.createClass({
    render: function () {
        
        return React.createElement(
            'ul',
            null,
            React.createElement(
                'li',
                null,
                'a'
            ),
            React.createElement(
                'li',
                null,
                'b'
            ),
            React.createElement(
                'li',
                null,
                'c'
            )
        )
        
    }
});

// 組件變成虛擬DOM
let ul = React.createElement(Uls, null);

// 渲染頁面
ReactDOM.render(ul, document.querySelector('.app'));

JSX語法

建立JSX語法的本質:使用基於XML的方式表達組件嵌套,保持和HTML一致的結構。最終全部的JSX都會編譯爲原生JavaScript

嵌套規則:標籤能夠任意嵌套。標籤閉合,必須嚴格閉合,不然沒法編譯經過。

編譯JSX語法:
工程化工具:fis-parse-babel2

fis.match('**.jsx', {
    parser: fis.plugin('babel2'),
    rExt: '.js'
});


// 渲染HTML內部的JSX語法

fis.match('**.html:jsx', {
    parser: fis.plugin('babel2')
});

JSX示例:

// 建立組件
let Uls = React.createClass({
    render: function () {
        return (
            <ul>
                <li>a</li>
                <li>b</li>
                <li>c</li>
            </ul>
        );
    }
});


// 渲染組件成 虛擬DOM
let ul = (<Uls></Uls>);

// 渲染頁面中
ReactDOM.render(ul, document.querySelector('.app'));

HTML內部JSX語法

<div class="app"></div>

<script src="lib/react.js" type="text/javascript" charset="utf-8"></script>
<script src="lib/react-dom.js" type="text/javascript" charset="utf-8"></script>

<script type="text/x-jsx">
    
    let div = (
        <div id="red">
            JSX
        </div>
    );
    
    ReactDOM.render(div, document.querySelector('.app'));
    
</script>

組件大體分類

  • APP 組件: 整個頁面的最完整組件

  • Header 組件: 頭部輸入組件

  • TodoList組件: 列表組件

  • TodoItem 組件: 列表項

  • Footer 組件: 底部操做組件

虛擬DOM屬性

爲虛擬DOM添加屬性,傳遞屬性的方式和HTML相同。

屬性能夠是字符串,也能夠是任意的JavaScrip變量。須要使用插值方式解析變量。

特殊屬性:
class,要使用成className
for, 要使用成htmlFor

// 建立組件
let Uls = React.createClass({
    render: function () {
        return (
            <ul className="listNone">
                <li>a</li>
                <li>b</li>
                <li>c</li>
            </ul>
        );
    }
});

對HTML組件

fuunction render () {
    return <p title={tit}>Hello</p>
}

React自定義組件

fuunction render () {
    return <p><CustomComponent></CustomComponent></p>
}

JSX花括號

插值形式,動態的改變虛擬DOM中屬性值,或者內容,或使用JavaScript表達式,作簡單的運算。

語法: {表達式}

'use strict';

// Component
let Header = React.createClass({
    render: function () {
        
        let userName = 'cyan';
        let date = new Date();
        
        return (
            <div className="header">
                <div className="inner">
                    <div className="left">
                        <span>{userName}</span>
                        &emsp;
                        <span>{date.getHours() > 12 ? '下午' : '上午'}</span>    
                    </div>
                </div>
            </div>    
        );
    }
});

// 渲染
ReactDOM.render(<Header />, document.querySelector('.app'));

JSX註釋

let Header = React.createClass({
    render: function () {
        {/* 這裏是註釋 */}
    }
});

Component

props屬性

組件中特殊屬性:props
做用:獲取組件上添加的屬性。

設置默認的屬性,經過getDefaultProps()來設置,是React內置方法名,在自定義方法的時候,不能重寫。

  • this.props : 獲取屬性值

  • geetDefaultProps(); : 獲取默認屬性對象,會被調用一次,當組件類建立的時候會被調用,返回值會被緩存起來,當組件被實例化事後若是傳入的屬性沒有值,會返回默認值屬性值。

  • this.props.children : 子節點屬性

  • propTypes : 屬性類型檢查

通常的,props規定是隻能讀取,應該禁止被修改。
緣由: React 不能幫檢查屬性類型(propTypes),修改props對象可能會致使預料以外的結果。

屬性數據的單項性

React的單項數據流模式,數據的流動管道就是 props,流動的方向就組件的層級自頂向下的方向。因此一個組件是不能修改自身的屬性,組件的屬性必定是經過父組件傳遞而來(或默認屬性)

'use strict';

// Component
let Prat = React.createClass({
    
    getDefaultProps: function () {
        return {
            title: ['默認標題']
        }
    },
    
    createLi: function () {
        
        return this.props.title.map( ( val, idx ) => {
            return (<li key={idx} >{ val }</li>);
        } );
        
    },
    
    render: function () {
        
//                    console.log( this.props.children );
        
//                    console.log( this.props );
        return (
            <div className="part">
                <ul className="header">
                    {this.createLi()}
                </ul>
            </div>
        );
        
    }
    
});

// 渲染
ReactDOM.render(<Prat />, document.querySelector('.app'));
ReactDOM.render(<Prat title={['新聞', '今日話題']} />, document.querySelector('.app1'));

style

設置style的樣式

  • 普通的CSS樣式, 遵循駝峯式命名規則

  • CSS3樣式,遵循大駝峯式命名規則

注意:樣式並不能像HTML行內同樣,須要使用插值方式,插值中使用對象。

'use strict';

// Componedt
let Style = React.createClass({
    
    render: function () {
        
        let sty = {
            color: 'red',
            border: '1px solid #000',
            borderBottom: '2px solid tan'
        }
        
        return (
            <h1 style={sty}>
                title
                <h1 style={{'background': 'tan' }}>titile2</h1>
            </h1>
        );
        
    }
    
});

// 渲染
ReactDOM.render(<Style />, document.querySelector('.app'));

Event

React中爲虛擬DOM添加事件與HTML爲DOM添加事件同樣: <div onClick="fn"></div>

通常的爲React添加的DOM事件,並不要字符串,須要使用插值符號爲虛擬DOM添加事件回調函數。

// Componedt
let Style = React.createClass({
    
    changeContent: function ( ev ) {
        
        ev.target.innerHTML = '修改後的文案';
        
    },
    
    render: function () {
        
        let sty = {
            color: 'red',
            border: '1px solid #000',
            borderBottom: '2px solid tan'
        }
        
        return (
            <div style={sty}>
                title
                <h1 style={{'background': 'tan' }} onClick={this.changeContent}>titile2</h1>
            </div>
        );
        
    }
    
});

// 渲染
ReactDOM.render(<Style />, document.querySelector('.app'));

state狀態

無狀態組件屬性

對於無狀態組件,能夠添加 .propTypes 和 .defaultProps 屬性到函數上。

若是一個在渲染頁面以後組件不會變化,能夠經過props就能夠實現對組件的樣式設置以及行爲渲染,此時組件不會收到外界的影響,組件是一成不變的,這類組件叫作: 無狀態satateless組件.

state

對於大部分的組件來講,一般是要通與外界交流,此時組件要處於不一樣的狀態,此時的組件就要有狀態,對於組件內部的狀態控制,能夠經過state屬性控制.

state屬性: 控制組件的內部狀態.

getInitialState() : 初始化狀態,
返回一個對象,或者數據,指代的就是 state

setState() : 設置狀態
參數:設置的值

state每次更新都會觸發一次render() 方法.
state通常的都是內部自定義方法來控制改變其狀態.

// 建立 Component
let Dom = React.createClass({
    
    getInitialState: function () {
        
        return {
            index: 0,
            txt: '嘻嘻哈哈'
        }
        
    },
    
    render: function () {
        
//                    console.log( this.state );
        
        return (
            <div>
                <button onClick={this.clickContent}>點擊顯示內容</button>
                <p>{this.state.txt}</p>
            </div>
        );
        
    },
    
    clickContent: function () {
        
        this.setState({
            txt: '麼麼噠'
        });
        
    }
    
});

// 渲染組件
ReactDOM.render(<Dom />, document.querySelector('.app'));

Component生命週期

clipboard.png

生命週期的方法都是在調用 React.createClass(); 的參數配置對象傳入.

組件規格

mixins

mixins: React的插件列表。經過這種模式在不一樣組件之間共享方法數據或者行爲只需共享mixin便可。
mixins內定義的生命週期方法在組件的生命週期內都會被調用

statics

statics : 定義組件的類方法。

// Component
let oDiv = React.createClass({
    
    // 定義組件類方法
    statics: {
        statisMethod: () => {
            return true;
        }
    },
    // Class 分爲類方法和實例方法, 實例方法能夠訪問this,而類方法不能。
    // 不能在Class中返回狀態或者屬性。
    
    render: function () {
        return (
            <div>嘻嘻哈哈</div>
        );
    }
});

// 渲染組件
ReactDOM.render(<oDiv />, document.querySelector('.app'));

displayName

displayName : 組件的名稱,JSX在轉爲JavaScript的時候自動設置displayName。 也能夠手動設置。

組件生命週期方法

整個組件的生命週期,包含:

  • 組件被實例化

  • 組件屬性改變

  • 組件狀態被改變

  • 組件被銷燬

clipboard.png

組件實例化

  • getDefaultProps() : 設置組件的屬性(props屬性)

  • getInitialSate() : 設置初始化狀態(state)

  • componentWillMount() : 組件即將被建立

  • render() : 渲染輸出虛擬DOM

  • componentDidMount() : 組件構建完成

componentWillMount()
條件: 第一次渲染階段在調用render方法前會被調用
做用: 該方法在整個生命組件只會被調用一次,能夠利用該方法作一些組件內部的初始化工做。

componentDidMount();
條件: 第一次渲染成功後,組件對應的DOM已經添加到頁面後調用.
做用: 這個階段表示組件對應的DOM已經存在,能夠在這個時候作一些依賴DOM的操做,或者其餘一些, 例如:請求數據,和第三方庫整合的操做。
若是嵌套了子組件,子組件會比父組件優先渲染,因此這個時候能夠獲取子組件對應的DOM。

// Component
let GoBack = React.createClass({
    
    getDefaultProps: function () {
        
        console.log(111);
        
        return {
            title: ''
        }
        
    },
    
    getInitialState: function () {
        console.log(222);
        
        return {
            sateteTitle: this.props.title
        }
        
    },
    
    componentWillMount: function () {
        
        console.log(333,this.satate, this.props);
        
    },
    
    render: function () {
        
        console.log(444);
        return (<div className="go-back">返回頂部</div>);
        
    },
    
    componentDidMount: function () {
        
        console.log(555);
        
        const _this = this;
        
        setTimeout(() => {
            
            _this.setState({
                stateTitle: '修改後title'
            });
            
        }, 1000);
        
    }
    
});

// 渲染 
ReactDOM.render(<GoBack />, document.querySelector('.app') );

在未初始化props以前,沒法使用this.props.xxx

組件存在期

一旦組件被建立,那麼就進入了組件的存在期,在存在期中,每次組件更新的時候,會進入新的5個階段.

  • componentWillReceivePros() : 表示組件將要接收新的屬性.

  • shouldComponentUpdate() : 組件是否應該更新.

  • componentWillUpdate() : 組件將要被更新

  • render() : 從新渲染組件

  • componentDidUpdate() : 組件已經被更新

componentWillReceivePros(newProps);
條件:當組件獲取新屬性的時候, 第一次渲染不會調用.
用處:這個時候能夠根據新的屬性來修改組件的狀態

獲取新的屬性,但並不能肯定屬性必定改變了,例如: 一個組件被屢次渲染到DOM中.

shouldComponentUpdate()
參數1:nextprops 下一個屬性
參數2: nextstate 下一個狀態
返回:返回布爾值,true表示更新組件,false表示不要對組件進行更新,後面階段不會執行.

條件:接收到新屬性或新狀態的時候在render前 會被調用(除了調用forceUpdate 和 初始化渲染之外)
用處:有機會絕對是否從新渲染組件。能夠優化應用性能(在多組件的狀況中)

componentWillUpdate()
參數1: nextProps 下一個屬性
參數2:nextState 下一個狀態

條件: 當組件肯定要更新,在render()以前被調用.
用處:能夠肯定必定會更新組件,能夠執行更新前作一些操做。
這個方法中不能使用 setState(); setState();的操做應該是在componentWillReceiveProps();方法中調用.

componentDidUpdate()
參數1:prevProps 前一個屬性
參數2:prevState 前一個狀態

條件:更新被應用到DOM以後
用處:能夠執行組件更新以後的操做。

存在期中的方法,在組件第一次渲染的時候,不會執行,componentWillReceiveProps();方法在組件內部狀態更新的是不會被調用.

銷燬期

組件生命週期的最後個階段,到了這個階段,也就是說,組件要被銷燬了。

componentWillUnmount()
組件即將在DOM樹中刪除
條件:組件銷燬的時候執行

生命週期與單項數據流

React的核心模式是單項數據流。在組件內部的生命週期中也是符合單項數據的模式。數據從組件的屬性流入,再結合組件的狀態,流入生命週期的方法,直到渲染結束,都應該是一個單向的過程,其間不能隨意改變組件的狀態。

子組件

子組件: 在組件內部使用其它組件的時候,組件被嵌套該組件中,做爲子組件使用.

做爲一個父組件的子組件,能夠經過屬性傳遞數據信息,直接在父組件中,對子組件添加屬性.
React是單項數據流,只能從父組件中的信息,傳遞給子組件.

注意:渲染組件的時候,只須要渲染父組件便可.

父組件傳遞數據信息給子組件方法:

1: 經過屬性傳遞數據信息,直接在父組件中對子組件添加屬性信息。

let Main = React.createCalss({
    
    render: function () {
        
        return (
            <div className="main">
                {/* 子組件 */}
                <GoBack title="返回組件title"/>
            </div>
        );
        
    }
    
});
// 缺點: 父組件向子組件中傳遞數據的時候,是固定的,當父組件更新的時候,沒拌飯更新子組件的屬性.

2: 經過父組件的屬性 {props}。 將父組件內部的數據傳遞子組件中.

let Main = React.createClass({
    
    getDefaultProps: function () {
        
        return {
            title: ''
        }
        
    },
    
    render: function () {
        
        return (
            <div className="main">
            {/* 子組件 */}
                <GoBack title={this.props.title} />
            </div>
        );
        
    }
    
});

3: 經過父組件的狀態 {state}。 將父組件內部的數據傳遞子組件中.

let Main = React.createClass({
    
    getDefaultProps: function () {
        
        return {
            title: ''
        }
        
    },
    
    getInitialState: function () {
        
        return {
            title: '麼麼噠'
        }
        
    },
    
    render: function () {
        
        return (
            <div className="main">
                {/* 子組件 */}
                <GoBack title={this.state.title} />
            </div>
        );
        
    }
    
});

組件的做用域,與JavaScript變量的做用域機制同樣.

子組件會尋找自身的prop屬性,state狀態。而後尋找父組件的prop屬性,state狀態。

兄弟組件的信息傳遞

每一個組件都有本身的完整空間,彼此之間沒有聯繫,如何實現兄弟組件之間的通訊。

父組件和子組件通訊,能夠經過設置子組件的屬性: 傳遞固定值,屬性值,狀態值,還能夠傳遞方法或者函數。

注意: 傳遞方法或者函數時:事件對象是組建綁定的元素。this指向父組件。

子組件向父組件傳遞消息,能夠經過父組件爲子組件添加函數,子組件經過調用該函數,傳遞參數數據來實現。

// InputMsg Component
const InputMsg = React.createClass({
    
    render: function () {
        
//                    console.log( this.props.changeMsg() );
        
        return (
            <div>
                <input type="text" onChange={this.props.changeMsg} />
            </div>
        );
    }
    
});

// App Component
const App = React.createClass({
    
    getInitialState: function () {
    
        return {
            msg: 'world'
        }
    
    },
    
    render: function () {
        
        return (
            <div className="mian">
                {/* 父組件傳遞方法 */}
                <InputMsg changeMsg={this.changeMsg} />
            </div>
        );
        
    },
    
    changeMsg: function ( ev ) {
//                    
        let vals = ev.target.value;
        
        console.log( vals );    
//                    console.log( ev );
//                    console.log( this );
        
    }
    
});

// render
ReactDOM.render(<App />, document.querySelector('.app'));

兄弟組件之間的通信,須要經過它們共同的父組件的state或者props來實現。
通常的,經過父組件的state來實現.

'use strict';

// 實現 組件之間的  雙向數據綁定

// InputMsg Component
const InputMsg = React.createClass({
    
    render: function () {
        
//                    console.log( this.props.changeMsg() );
        
        return (
            <div>
                <input type="text" onChange={this.props.changeMsg} />
            </div>
        );
    }
    
});

// ShowMsg Component
const ShowMsg = React.createClass({
    
    getDefaultProps: function () {
        return {
            msg: '嘻嘻哈哈' 
        }
    },
    
    render: function () {
        return (
            <div>
                <p>{ this.props.msg }</p>
            </div>
        );
    }
    
});

// App Component
const App = React.createClass({
    
    getInitialState: function () {
    
        return {
            msg: 'world'
        }
    
    },
    
    render: function () {
        
        return (
            <div className="mian">
                <InputMsg changeMsg={this.changeMsg} />
                <ShowMsg msg={this.state.msg} />
            </div>
        );
        
    },
    
    changeMsg: function ( ev ) {
        
        let vals = ev.target.value;
        
        this.setState({
            msg: vals
        });
        
    }
    
});

// render
ReactDOM.render(<App />, document.querySelector('.app'));

4,子組件傳遞信息給父組件

子組件向父組件傳遞消息,能夠經過父組件爲子組件添加函數實現,子組件經過調用該方法,並經過處理以後的數據用參數形式傳遞給父組件來完成。

父組件定義方法,子組件調用方法

事件處理與合成事件

React只需把事件處理器,以駝峯命名形式看成組件props傳入。就像是用普通HTML事件同樣。
React內部建立一套合成事件系統來使全部在IE8和以上瀏覽器表現一致,也就是說,React懂得處理冒泡和捕獲事件,事件對象的參數與W3C規範一致。

須要在手機或平板等觸摸設備上使用React,在React版本0.14自動開啓觸屏事件。

findAllInRenderedTree

自動綁定和事件代理

AutoBinding: 在JavaScript裏建立回調函數的時候,保證this的正確性,通常都須要顯示的綁定方法到它的實力上, React全部方法被自動綁定到它的組件實例上。

事件代理: React並無把時間處理器綁定到節點本省。當React啓動的時候,它在最外層使用一個惟一的事件監聽器處理全部時間。當組件被加載和銷燬時,只是在內部映射裏添加或刪除事件處理器。當事件觸發,React根據映射來決定如何分發。當映射裏處理器時,會看成空操做處理。

組件實際上是狀態機

React 把用戶界面看成簡單狀態機。把用戶界面想象成擁有不一樣狀態而後渲染這些狀態,能夠輕鬆讓用戶界面與數據保持一致。

React中,只須要更新組件的state,而後根據新的state從新渲染用戶界面(不要操做DOM)。React來決定如何最高效的更新DOM。

state工做原理

經常使用的通知React數據變化的方法時調用 setState(data, callback); 這個方法會合並(merge) data 到 this.state ,並從新渲染組件。渲染完成後,調用可選的callback回調。大部分狀況下不須要提供callback,由於React會負責把界面更新到最新的狀態。

哪些組件應該有State

大部分組件的工做應該是衝 props 裏面 取出數據並渲染。可是,有時候須要和用戶俗話如,服務器請求數據,或者時間變化等作出相應,這時才需使用State。

嘗試把儘量多的組件無狀態化這樣作能隔離state , 做用: 把它放到最合理的地方,也能減小冗餘,同時易於解釋程序運做過程。

經常使用的模式是:建立多個只負責渲染數據的無狀態組件,在它們的上層建立一個有狀態的組件並把它的狀態經過props傳給子級。這個有狀態的組件封裝了全部用戶的交互邏輯,而這些無狀態組件負責聲明式的渲染數據。

哪些應該做爲State

state應該包括那些可能被組件的事件處理器改變並觸發用戶界面更新的數據。真實的應用中這種數據通常都很小且能被JSON序列化。當建立一個狀態化的組件時,想象一下表示它的狀態最少須要哪些數據,並只會把這些數據存入 this.state。在render() 裏再根據state來計算須要的其它數據。
若是在state裏添加冗餘數據或計鎖的數據,須要常常手動保持數據不一樣步,不能讓React來幫助處理。

  • 用戶相關

  • 後臺數據

  • 事件須要的數據

哪些不該該做爲 State

this.state 應該僅包括可以表示用戶界面狀態所需的最少數據。 不該該包括state:

  • 計算所得數據: 不要擔憂state 來預先計算數據 -- 把全部的計算都放在render() 裏面更容易保證用戶界面和數據的一致性。

  • React組件: 在render()裏使用當前 props和state 來建立它。

  • 基於props的重複數據: 儘量的使用props來做爲惟一數據源。把props保存到state的一個有效的場景是須要知道它之前的值的時候,由於將來的props可能會變化。

React與DOM

獲取DOM元素

第一種方式:
對於表單使用:ref="names" 來定義表單中的屬性

獲取使用: this.refs.names
做用:通常使用獲取表單元素中的值

第二種方式:
findDOMNode();
參數:組件實例。

通常在組件實例化完成階段使用componentDidMount
獲取整個實例化後的真實DOM

注意:不能使用在無狀態組件上.

const Checkbox = React.createClass({
    
    getInitialState: function () {
        
        return {
            cb1: false,
            cb2: false
        }
        
    },
    
    render: function () {
        
        return (
            
            <div>
                <button onClick={this.showReslut}>結果</button>
                <input ref="cb1" type="checkbox" defaultChecked="true" onChange={this.change} />籃球
                <input ref="cb2" type="checkbox" />足球
            </div>
            
        );
        
    },
    
    componentDidMount: function () {
        
        let dom = ReactDOM.findDOMNode(this);
        
        let inps = ReactDOM.findDOMNode( this.refs.cb1 );
        // 獲取 this.refs.cb1 的 所在DOM,並不能傳入 this.refs。
        
    },
    
    showReslut: function () {
        
        console.log( this.refs.cb1.checked, this.refs.cb2.checked );
        
    },
    
    change: function ( ev ) {
        
        let cheVals = ev.target.checked;
        
        this.setState({
            'cb1': cheVals 
        });
        
    }
    
});

// render
ReactDOM.render(<Checkbox />, document.querySelector('.app'));

非元素屬性

非元素屬性: 不是DOM元素原生就有的屬性。(例如:自定義屬性,React提供的特殊屬性,ref等)

'use strict';

let Search = React.createClass({
    render: function () {
        
        // 模擬搜索以後文案顯示
        let content = {
            __html: '<span style="color: cyan">搜索結果,麼麼噠</span>'
        }
        
        return (
            <div className="search-grpup">
                <input ref="serachInput" type="text" />
                <button onClick={this.clickSearch}>搜索</button>
                <span dangerouslySetInnerHTML={content}></span>    
                {/* 使用行內式的樣式,須要經過 dangerouslySetInnerHTML屬性設置 */}
            </div>
        );
    },
    clickSearch: function ( ev ) {
        
        let vals = this.refs.serachInput.value;
        
        console.log(vals);
        
    }
});

// 渲染
ReactDOM.render(<Search />, document.querySelector('.app'));

key: 列表中元素的ID。經過設置key是的每一個列表元素獲取ID
ref : 獲取表單或組件內部的元素的 文本節點,value值
dangerouslySetInnerHTML : 設置元素的內容,該屬性對應的值爲一個對象, 對象中是React定義的: __html屬性對應值,會渲染到元素中. (對應值:能夠是文本節點,標籤節點);

定義:

let content = {
    __html: '<span style="color: cyan">搜索結果,麼麼噠</span>'
}

使用:

<span dangerouslySetInnerHTML={content}></span>

約束性組件和非約束性組件

約束性組件:狀態是交由組件自身管理(state是經過初始化,自定義方法設置狀態)
非約束性組件:狀態是交由元素自身管理

通常的,約束性組件與非約束性組件是對錶單元素而言的。

非約束性組件

非約束性組件,表單值與是由用戶輸入。

'use strict';

// Component
const Search = React.createClass({
    
    clickBtn: function ( ev ) {
        
        let vals = this.refs.serchInput.value;
        
        console.log(vals);                    
        
    },
    
    render: function () {
        return (
            <div className="serach">
                <div className="serach-logo">
                    {/* <input ref="serchInput" type="text" placeholder="用戶輸入的內容" /> */}
                    <input ref="serchInput" type="text" defaultValue="用戶輸入的內容" />
                    <button onClick={this.clickBtn}>搜索</button>
                </div>
            </div>
        );
    }
    
});

// render
ReactDOM.render(<Search />, document.querySelector('.app'));

placeholder與defaultValue的區別:
placeholder與defaultValue都是顯示文案,defaultValue在編譯後會變成value值

獲取表單內的內容須要設置ref="names",獲取須要:this.refs.names。
這種方式,元素的狀態信息保存在元素自己,所以它是一種非約束性組件.

約束性組件

表單元素的value值交給組件的state管理,稱之爲: 約束性組件。
當表單元素改變的時候,能夠經過onChange()事件來獲取,顯性修改state,經過state來渲染新的input的value值。

優勢:元素的值交由組件管理,表單驗證更加靈活。

'use strict';

const Search = React.createClass({ 
    
    getInitialState: function () {
        
        return {
            inp: '默認狀態',
            txt: ''
        }
        
    },
    
    render: function () {
        return (
            <div className="search">
                <div className="search-group">
                    <input type="text" placeholder={this.state.inp} onChange={this.inpChange} />
                    <button>百度一下</button>
                    <span>{this.state.txt}</span>
                </div>
            </div>
        );
    },
    
    inpChange: function ( ev ) {
        
        let vals = ev.target.value;
        
        if ( vals.length > 10  ) {
            
            this.setState({
                inp: vals,
                txt: '不能超過10個字符'
            });
            
        }
        
    }
});

// 渲染
ReactDOM.render(<Search />, document.querySelector('.app'));

幾種約束性組件

select
經過value,或者defaultValue值來控制.

'use strict';

const  Select = React.createClass({
    
    // 初始化 狀態
    getInitialState: function () {
        
        return {
            selectValue: ''
        }
        
    },
    
    render: function () {
        
        return (
            <div>
                <select defaultValue={this.state.selectValue} onChange={this.changeSelect}>
                    <option value="cyan">cyan</option>
                    <option value="tan">tan</option>
                    <option value="khaki">khaki</option>
                </select>
                <span></span>
            </div>
        );
        
    },
    
    changeSelect: function ( ev ) {
        
        let vals = ev.target.value;
        
        this.setState({
            selectValue: vals
        });
        
    }
    
});

// render    
ReactDOM.render(<Select />, document.querySelector('.app'));

若是使用ref來獲取表單元素中的內容,使用default加前綴,例如: defaultValue,defaultChecked. 。經過refs來獲取值

'use strict';

const Checkbox = React.createClass({
    
    getInitialState: function () {
        
        return {
            cb1: false,
            cb2: false
        }
        
    },
    
    render: function () {
        
        return (
            
            <div>
                <button onClick={this.showReslut}>結果</button>
                <input ref="cb1" type="checkbox" defaultChecked="true" onChange={this.change} />籃球
                <input ref="cb2" type="checkbox" />足球
            </div>
            
        );
        
    },
    
    showReslut: function () {
        
        console.log( this.refs.cb1.checked, this.refs.cb2.checked );
        
    },
    
    change: function ( ev ) {
        
        let cheVals = ev.target.checked;
        
        this.setState({
            'cb1': cheVals 
        });
        
    }
    
});

// render
ReactDOM.render(<Checkbox />, document.querySelector('.app'));

與其它庫一塊兒使用

侵入式插件

並不必定是使用React的組件的生命週期事件

須要在componentDidMountcomponentDidUnUpdate 放置其它庫的邏輯代碼.

也能夠這種方式來綁定事件監聽,甚至事件流

混合

React支持混合, 將混合中的方法賦值到組件對象上。組件對象可使用混合中定義的方法。

通常是自定義方法,放置mixin中。

使用混合,值是一個數組,複製多個對象上面的屬性和方法。混合能夠看作是一種多繼承。

定義:

let MixinMethod = {}

使用:

mixins: [MixinMethod]

Airbnb React

基本規則

  • 每一個文件只包含一個React組件
    可是 無狀態,或者Pure組件容許一個文件包含多個組件。

  • 始終使用JSX語法

  • 不要使用React.createElement方法,除非初始化app的文件不是JSX格式.

  • 一個組件實現一個功能。

  • 組件的生命週期方法按照排序編寫

React組件的內部方法命名不要使用下劃線前綴。

命名

擴展名: React組件使用.jsx擴展名
文件名:文件名使用帕斯卡命名。 例如: ReservationCard.jsx
引用命名:React組件使用帕斯卡命名,引用實例採用駱駝命名

import reservationCard from './ReservationCard';

const ReservationItem = <ReservationCard />

組件命名: 組件名稱應該和文件名一致。 例如:Reservation.jsx 中 有一個Reservation 的引用名稱。可是,若是是在目錄中的組件,應該使用 index.jex做爲文件名而且使用文件夾名稱做爲組件名.

相關文章
相關標籤/搜索