React -- 数据流

在React中,数据是从父组件到子组件流动的,这条原则可以让我们只需要在父组件上操作,然后子组件就会自动更新并渲染。

这一节有两个很重要的概念:React组件的state和props。
如果初始化父组件的props,那么React就会向下遍历组件树,尝试渲染相关的子组件;而state则只涉及组件自己内部的状态,这些状态不会干扰到组件的父/子节点,仅和组件自身有关。

state

内置方法setState:当我们调用这个方法后,由于组件的状态改变,这时候,组件就会尝试重新渲染。

在React中,常常在事件处理方法中更新state,例如按钮绑定的方法等等。

一个栗子:(本栗采用ES6 class的语法方式构建组件)

import React, { Component } from 'react';
class Counter extends Component { 
    constructor(props) {
        super(props);
        this.handleClick = this.handleClick.bind(this);
        this.state = { 
            count: 0,
        }; 
    }
    handleClick(e) {
        e.preventDefault();
        this.setState({
            count: this.state.count + 1,
        }); 
    }
    render() { 
        return (
            <div>
                <p>{this.state.count}</p>
                <a href="#" onClick={this.handleClick}>  </a>
            </div> 
        );
    } 
}

props

首先给出Tab组件的基本方法,本节我们将在这个控件的基础上学习:

class Tabs extends Component { 
    constructor(props) {
        super(props); 
    }
    // ...
    render() {
        return <div className="ui-tabs"></div>;
    } 
};

下面进入正题:

props是React用来让组件之间相互联系的机制,通俗的说,就好像是方法的参数。开发者利用props,可以在React组件之间传递数据。

组件的props一定来自于默认属性或从父组件传递而来,如果我们试图在代码中修改props的原始值,React将会报错。

栗子:

<Tabs classPrefix={'tabs'} defaultActiveIndex={0}>
    <TabPane key={0} tab={'Tab 1'}> Tab1content   </TabPane> 
    <TabPane key={1} tab={'Tab 2'}> Tab2content   </TabPane>  
    <TabPane key={2} tab={'Tab 3'}> Tab2content   </TabPane>
</Tabs>

在组件Tabs中,classPrefix和defaultActiveIndex都是组件的props。

1、子组件prop

在React中有一个重要且内置的prop:children,它代表组件的子组件的集合。例如,上面这个Tabs的子组件就是:

    <TabPane key={0} tab={'Tab 1'}> Tab1content   </TabPane> 
    <TabPane key={1} tab={'Tab 2'}> Tab2content   </TabPane>  
    <TabPane key={2} tab={'Tab 3'}> Tab2content   </TabPane>

那么,父组件Tabs渲染子组件TabPane的方法就是:


getTabPanes() {
    const { classPrefix, activeIndex, panels, isActive } = this.props;
    return React.Children.map(panels, (child) => { 
        if (!child) { return; }
        const order = parseInt(child.props.order, 10);
        const isActive = activeIndex === order;
        return React.cloneElement(child, { 
            classPrefix,
            isActive,
            children: child.props.children, 
            key: `tabpane-${order}`,
        }); 
    });
}

这段代码完成的功能是渲染子组件。通过方法map遍历子组件,同时将order, isActive, children, key利用cloneElement方法克隆到一个新创建的TabPane组件中,然后返回这个新的组件集合。这样,在我们需要的时候,调用方法getTabPanes即可完成对组件的渲染。

2、其他组件prop

在前面的栗子中,组件prop我们传入的是一个固定值:

<TabPane key={0} tab={'Tab 1'}>    Tab1     </TabPane>

但是,其实prop的强大之处在于,我们可以向其中传入动态值,甚至节点(component props)。

栗子:

<Tabs classPrefix={'tabs'} defaultActiveIndex={0} className="tabs-bar">             
    <TabPane
        order="0"
        tab={<span><i className="fa fa-home"></i>&nbsp;Home</span>}>    
    </TabPane>
    <TabPane
        order="1"
        tab={<span><i className="fa fa-book"></i>&nbsp;Library</span>}>
    </TabPane>
    <TabPane
        order="2"
        tab={<span><i className="fa fa-pencil"></i>&nbsp;Applications</span>}>     
    </TabPane> 
</Tabs>

这样,配合上相关的渲染代码,在渲染后,我们就可以在每个TabPane中,插入新的元素。

渲染的关键在于遍历所有tabpane组件的tab prop,进行必需的操作后,将它们返回。

3、用function prop与父组件通信。

state的通信集中在组件内部,而对于prop,它的通信则是父组件向子组件传播。

4、propTypes

propTypes用于规范props的类型和必需的状态:如果组件定义了propTypes,那么在开发环境下,就会对prop的值新型类型检查,如果传入的prop与要求的类型不匹配,React将会在控制台中报出warning。
栗子:

static propTypes = {
    classPrefix: React.PropTypes.string, 
    className: React.PropTypes.string,  
    defaultActiveIndex: React.PropTypes.number, 
    activeIndex: React.PropTypes.number.isRequired,// 必需
    onChange: React.PropTypes.func,// func 不是 function,另外,对于布尔类型是bool 而不是 boolean
    children: React.PropTypes.oneOfType([
        React.PropTypes.arrayOf(React.PropTypes.node),
        React.PropTypes.node, 
    ]),
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值