<react学习笔记(3)>属性与状态以及组件的生命周期(初始化阶段)

334 阅读4分钟

1.属性和状态

1.属性props
  1. 含义:props = properties
  2. 属性:一个事物的性质与关系,属性往往是与生俱来的,无法自己改变的
  3. 属性的两种用法:
    a). "?"中的内容可以是:字符串,对象{},数组{[1,2,3]},变量{var}
    b). <Demo {...props} />
    var props = { one : "123", two : "456" }
  4. getDefaultProps : 设置默认属性 第一个调用
2.状态state
  1. 状态 :事务所处的状况
    状况是由食物自行处理,不断变化的。父组件与子组件都无法改变他的状态。
  2. 状态的用法:
    a). getInitialState : 初始化状态
    b). setState : 更新状态

属性和状态相似点 :
a). 都是纯js对象,使用{}创建的对象
b). 都会触发render更新
c). 都具有确定性,给定相同的属性或者相同的状态,结果是相同的

属性和状态的区分: 组件在运行时需要修改的数据就是状态,所有的数据都可以变成状态

以下是例子

//demo1 :属性的第一种写法
<div id="demo1"></div>
<script type="text/babel">
    var oDemo = document.getElementById("demo1"),
        Demo = React.createClass({
        render(){
            return <div>{this.props.title}</div>
        } 
    });
    ReactDOM.render(<Demo title={"Demo"}/>, oDemo);
    //this.props.title表示的就是title={"Demo"},因此在浏览器上会显示出Demo这个单词
</script>
//demo2 :属性的第二种写法
<div id="demo2"></div>
<script type="text/babel">
    var oDemo = document.getElementById("demo2"),
        Demo = React.createClass({
            render(){
                return (<div>
                    <div>{this.props.title}</div>
                    <a {...this.props}>{this.props.title}</a>
                </div>)
    {/*
        ...this.props
        props提供的一个语法糖,可以将父组件中的全部属性复制给子组件,
        如果是这个标签本身拥有的这个属性,则全部复制给子组件;反之没有效果
    */}
                );
            }
        });
    var props = {
        title : "百度",
        href : "http://www.baidu.com"
    };
    ReactDOM.render(<Demo {...props}/>, oDemo);
</script>
3.this.props.children属性

children没有与组件的属性一一对应,表示组件的所有子节点,一般用于列表。

例子

<div id="demo3"></div>
<script type="text/babel">
    var oDemo = document.getElementById("demo3"),
        List = React.createClass({
            render(){
                return (<ul>
                    {   /*
                            列表项的数量以及内容不确定,在创建模板的时候菜确定。
                            利用this.props.children从父组件获取需要的内容。
                            利用React.Children.map方法进行children的遍历。
                            用遍历的时候需要加{}。
                            map函数会返回值,存在child中。
                        */
                        React.Children.map(this.props.children, function(child){
                            return <li>{child}</li>;
                        });   
                    }
                </ul>);
            }   
        });
    ReactDOM.render(<List>
                        <h1>百度</h1>
                        <a href="http://www.baidu.com">http://www.baidu.com</a>
                    </List>, oDemo);
</script>

demo3运行后html会变成如下:

<div id="demo3">
    <ul data-reactroot="">
        <li>
            <h1>百度</h1>
        </li>
        <li>
            <a href="http://www.baidu.com">http://www.baidu.com</a>
        </li>
    </ul>
</div>

状态state的例子

//demo4 state
<div id="demo4"></div>
<script type="text/babel">
    var oDemo = document.getElementById("demo4"),
        Demo = React.createClass({
            //设置初始的状态 getInitialState
            getInitialState(){
                return {
                    // 这里的值可以是一个boolean,string,function
                    onOff : true;
                };
            },
            handleClick(){
                // 通过点击事件来修改状态值,原来的状态值需要使用this.state获取
                this.setState({
                    //取反
                    onOff: !this.state.onOff
                });
            },
            render(){
                return (<div onClick={this.handleClick}>{this.state.onOff ? "data1":"data2"}</div>);
                //当点击时,按照onOff属性的改变而改变值
            }
        )};
    ReactDOM.render(<Demo />, oDemo);
</script>

小案例:本地时间的显示

//demo5
<div id="demo5"></div>
<script type="text/babel">
    var oDemo = document.getElementById("demo5"),
        Demo = React.createClass({
            //设置默认的属性
            getDefauleProps(){
                return{
                    name : "现在的时间是:"
                };
            },
            //设置初始的状态 getInitialState
            getInitialState(){
                return {
                    time: new Date().toLocaleTimeString(); 
                };
            },
            change(){
                // 在定时器中使用this.setState的时候需要将这个this变保存起来
                var that = this;
                setInterval(function(){
                    that.setState({
                        time: new Date().toLocaleTimeString(); 
                    });
                },1000);
            },
            render(){
                return (<div onClick={this.change()}>{this.props.name}{this.state.time}</div>);
            }
        )};
    ReactDOM.render(<Demo name="北京时间: "/>, oDemo);
</script>

2.组件的生命周期(初始化阶段)

生命周期:组件的本质是状态机,输入确定,输出一定确定。 一个state对应一个render,状态转换的时候会触发不同的函数。

生命周期的三个阶段:

  1. 初始化阶段 : 设置初始的属性与状态
    a). getDefaultProps: 设置初始的属性,只在第一次调用,实例之间共享引用。
    b). getInitialState: 设置初始的状态。
    c). componentWillMount: 组件将要加载,render之前最后一次修改状态的机会。
    d). render: 只能访问this.props和this.state,只有一个顶层标签(组件),不允许修改状态和DOM输出。
    e). componentDidMount: 成功render并渲染完成真实DOM之后出发,可以修改DOM,要操作DOM也必须在这个阶段完成。

例子

//demo1
<div id="demo6"></div>
<script type="text/babel">
    var oDemo = document.getElementById("demo6"),
        Demo = React.createClass({
            //第一步:设置初始的属性,只执行一次
            getDefaultProps(){
                return {
                    name1: "一个盒子",
                    title: "box"
                };
            },
            
            //第二步:设置初始的状态(可以将属性改成状态)
            getInitialState(){
                return {
                    name2: this.props.name1
                };
            },
            
            //第三步:组件将要加载的时候,最后一次可以修改状态的机会
            componentWillMount(){
                this.setState({
                    name2: "最后一次修改机会"
                });
                //第三步中是无法获取到节点的
            },
            
            //第四步:render渲染
            render(){
                var styles = {
                    position:'absolute',
                    width: '100px',
                    height: '100px',
                    color: 'red',
                    background: 'lime'
                };
                return <div ref="box" style={styles}>{this.props.title}{this.state.name2}</div>;
            },
            
            //第五步:组件完成加载,只有在这一个阶段,才可以操作DOM节点
            componentDidMount(){
                var box = this.refs.box, //父级引用子级
                    timer = null,
                    n = 0;
                    box.onclick = function(){
                        var that = this;
                        timer = setInterval(function(){
                            n++;
                            that.style.left = n + "px";
                        },100);
                    };
                
            }
        });
    ReactDOM.render(<Demo />, oDemo);
</script>

效果图: 点击后会慢慢往右移动