React學習筆記—UI交互

props

先看個簡單的例子:數組

var HelloWorld = React.createClass({
    render: function () {
        return (
            <div data-title={this.props.title}>{this.props.content}</div>
        )
    }
});

React.render(
    <HelloWorld title="this is title" content="this is content"/>,
    document.body
);

看代碼就很容易理解:經過this.props咱們能夠拿到組件使用時的屬性。稍微改變下代碼,咱們打印出this.props瞅瞅:瀏覽器

var HelloWorld = React.createClass({
    render: function () {
        return (
            <div data-title={this.props.title}>{JSON.stringify(this.props)}</div>
        )
    }
});

React.render(
    <HelloWorld title="this is title" content="this is content"/>,
    document.body
);

瀏覽器頁面效果:服務器

圖片描述

能夠看出this.props就是組件的屬性集合,稍微改下代碼,再來看看:函數

var HelloWorld = React.createClass({
    render: function () {
        return (
            <div>{JSON.stringify(this.props)}</div>
        )
    }
});

React.render(
    <HelloWorld title="this is title">
        <span>1</span>
        <span>2</span>
    </HelloWorld>,
    document.body
);

瀏覽器頁面效果:this

圖片描述

這個時候多了一個children的屬性,React將組件的子節點封裝到了children屬性中,若是想獲取到子節點的內容,能夠這麼寫:spa

var HelloWorld = React.createClass({
    render: function () {
        return (
            <div>
            {
                this.props.children.map(function (child) {
                        return child;
                })}
            </div>
        )
    }
});

React.render(
    <HelloWorld title="this is title">
        <span>1</span>
        <span>2</span>
    </HelloWorld>,
    document.body
);

當子節點只有一個的時候直接經過this.props.children獲取子節點。當子節點的個數大於1,this.props.children是一個數組。3d

綜上咱們能夠看出,React將節點屬性和子節點都封裝到props當中,咱們能夠經過this.props獲取到。在React的設定中,props是不可變的,當props屬性肯定後,咱們不該該再去手動修改它。代理

一個陷阱

看下這個代碼:code

var Hello = React.createClass({
    render: function () {
        return (
            <div></div>
        )
    }
});

React.render(
    <Hello>
        <p>content</p>
    </Hello>,
    document.body
);

咋一看是否是以爲頁面渲染出來應該是這個效果:blog

<div>
    <p>content</p>
</div>

實際上渲染出來是這樣的:

<div></div>

看頁面的渲染效果:咱們要找到根節點,關注它的render方法的返回值。至於使用時的嵌套結構,看完props應該明白,這些都是組件屬性,想要使用的話,請經過this.props.children.

state

state是同UI交互最重要的屬性,看個簡單的例子,點擊按鈕,切換按鈕的顏色:

var ColorButton = React.createClass({
    getInitialState: function () {
        return {bColor: 'green'};
    },
    render: function () {
        return (
            <button onClick={this.handleClick} style={{backgroundColor: this.state.bColor}}>click</button>
        )
    },
    handleClick: function (event) {
        this.setState({bColor: this.state.bColor === 'green' ? 'red' : 'green'});
    }
});

React.render(
    <ColorButton />,
    document.body
);

getInitialState是用來初始化state,handleClick是用來處理咱們點擊事件的。

事件機制

React實現了本身的一套事件代理和處理機制,這套機制是符合W3C標準的。經過這套機制,React有兩個很重要的特色:

自動綁定

全部的事件處理函數當中的this指向組件的實例。若是想要拿到當前操做的DOM,經過參數event獲取。

var ColorButton = React.createClass({
    getInitialState: function () {
        return {name: 'button'};
    },
    render: function () {
        return (
            <button onClick={this.handleClick}>click</button>
        )
    },
    handleClick: function (event) {
        console.log(this.state);
        console.log(event.target);
    }
});

React.render(
    <ColorButton />,
    document.body
);

事件代理

React並無將事件處理添加到相應的每一個節點上。當React啓動時,在根節點上監聽全部的事件,並管理事件到相應節點的映射。當組件mounted或者unmounted時,事件將會被添加到映射關係或者被刪除。我感受,有點jQuery的事件代理的意思:

#糟糕的寫法
$('li').on('click', function () {
    //todo
});

//好點的寫法
$('ul').on('click', 'li', function () {
    //todo
});

狀態機

React將UI簡單的看做狀態機。看UI看做各類各樣的狀態,並在各類狀態間切換,很容易保持UI的一致性。在React中,你只要改變組件的狀態,就會從新渲染UI,React會在最有效的方式下更新DOM。

state工做原理

經過調用setState(data, callback)方法,改變狀態,就會觸發React更新UI。大部分狀況下,咱們不須要提供callback函數。React會自動的幫咱們更新UI。

後面在好好看看這個callback的功能和調用時機。

什麼樣的組件該有state

大部分的組件應該從props屬性中獲取數據並渲染。但有的時候組件得相應用戶輸入,同服務器交互,這些狀況下會用到state。React的官方說法是:儘量的保持你的組件無狀態化。爲了實現這個目標,得保持你的狀態同業務邏輯分離,並減小冗餘信息,儘量保持組件的單一職責。

React官方推薦的一種模式就是:構建幾個無狀態的組件用來渲染數據,在這些之上構建一個有狀態的組件同用戶和服務交互,數據經過props傳遞給無狀態的組件。個人理解大概就是這樣:

var RenderComponent = React.createClass({
    render: function () {
        return (
            <ul>
                {
                    this.props['data-list'].map(function (item) {
                        return (<li>{item}</li>)
                    })
                }
            </ul>
        )
    }
});


var StateComponent = React.createClass({
    getInitialState: function () {
        return {list: ['xxx', 'yyy']};
    },
    render: function () {
        return (
            <div>
                <button onClick={this.handleClick}>click</button>
                <RenderComponent data-list={this.state.list}/>
            </div>

        )
    },
    handleClick: function () {
        this.setState({list: [1, 2, 3]});
    }
});

React.render(
    <StateComponent />,
    document.body
);

state應該包含什麼樣的數據

UI交互會致使改變的數據。

state不該包含什麼樣的數據

  • 計算過的數據
  • 組件
  • 從props複製的數據

state應保含最原始的數據,好比說時間,格式化應該交給展示層去作。

組件應在render方法裏控制。

相關文章
相關標籤/搜索