react学习笔记

1:组件的编写形式:

  1.1 直接写在同一个页面:

import React from 'react';
import { Link, Router, Route } from 'react-router-dom';
import { browserHistory } from 'react-router';
import * as routePaths from './../constants/routePaths';
class Welcome extends React.Component {
       render() {         
         return (
             <div className="welcome">
                 <h1>click me{this.props.name}</h1>
             </div>
         );
      }
}
class Index extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
        };
        
        this.handle = this.handle.bind(this);    
    }

    handle() {
        alert('你看你看~');
    }

       render() {         
         return (
             <div className="wrapper">
                 <Welcome></Welcome>
                     <h1 onClick={this.handle}>这是首页</h1>
                     <div className="mc">
                         <Link to={routePaths.CARD}>
                             <button>点击跳转</button>
                         </Link>
                     </div>
             </div>
         );
      }

}

export default Index;

1.2 写在外面

 

       

 

2:传入props的不同:

 3. 嵌套组件:

最外层;

import React from 'react';
import { Link, Router, Route } from 'react-router-dom';
import { browserHistory } from 'react-router';
import * as routePaths from './../constants/routePaths';
import Welcome from './../../component/Welcome.jsx';

class Index extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
        };
        
        this.handle = this.handle.bind(this);    
    }

    handle() {
        alert('你看你看~');
    }

       render() {         
         return (
             <div className="wrapper">
                 <Welcome name='sara'></Welcome>
                 <Welcome name='xiaohua'></Welcome>
                 <Welcome name='lili'></Welcome>
                 <Welcome name='sss'></Welcome>
                     <h1 onClick={this.handle}>这是首页</h1>
                     <div className="mc">
                         <Link to={routePaths.CARD}>
                             <button>点击跳转</button>
                         </Link>
                     </div>
             </div>
         );
      }

}

export default Index;

welcome组件:

import React from 'react';
import UserInfo from './UserInfo.jsx';

class Welcome extends React.Component {
       render() {         
         return (
             <div className="welcome">
                 <h1>click me--{this.props.name}</h1>
                 <UserInfo age="14"></UserInfo>
             </div>
         );
      }
}
export default Welcome;
UserInfo 组件:
import React from 'react';

class UserInfo extends React.Component {
       render() {         
         return (
             <div className="user-info">
                 <h4>我的年龄是{this.props.age}</h4>
             </div>
         );
      }
}
export default UserInfo;

4:super中类的继承

如果你用到了constructor就必须写super(),是用来初始化this的,可以绑定事件到this上;
如果你在constructor中要使用this.props,就必须给super加参数:super(props)
(无论有没有constructor,在renderthis.props都是可以使用的,这是React自动附带的;)
如果没用到constructor,是可以不写的,直接:

<h1>Hello, {this.props.name}!</h1>

 

 

5: ES6中规定 类中方法之间不需要逗号分隔,加了会报错。

`React.createClass`是react刚开始推荐的创建组件的方式,这是ES5的原生的JavaScript来实现的React组件;

 

该方法内部的函数之间有逗号分隔:

React.Component是以ES6的形式来创建react的组件的,是React目前极为推荐的创建有状态组件的方式,ES6中规定 类中方法之间不需要逗号分隔,加了会报错。

不同之处:

createClass 方法接受一个 getInitialState 函数作为参数一部分,这个函数会在组件挂载(mount)时被调用一次。

ES6 class 使用构造函数。在调用 super 之后,直接设置 state 即可。

Facebook 已经声明 React.createClass 最终会被 ES6 class 取代,不过他们也说「我们不会废弃 React.createClass,直到我们找到目前 mixin 用例的替代方案,并且在语言中支持类属性初始化器

 目前在react较高版本中使用 createClass 会报错:

react最新版本抛弃使用了createClass这个函数,这个也是为了配合ES6 ,与时俱进。

 

 

6:state的问题(解决该问题的方法详见http://www.cnblogs.com/xiaozhumaopao/p/8311307.html)

6.1  在函数中改变或者获取state

handleClock(){
    this.setState({isRender: false});
}

报错:

原因是es6中 取消了this的指向,我们可以在 constructor 中来改变 this.handleClick 执行的上下文

componentWillUnmount方法原本是挂载的组件卸载的时候执行的,但是我用下面的方法却不行:

       render() {         
         return (
             <div className="wrapper">
                 <Clock name="xiahua" />
                 <div onClick={this.handleClocks}>移除</div>
             </div>
         );
      }

      handleClocks(){
          let wrapper = document.querySelector('.wrapper');
          let clockdom = document.querySelector('.clocks');
          wrapper.removeChild(clockdom);
      }

这样的原因是,真正的dom节点消失,而组件的卸载指的是render的时候取消渲染对应的虚拟dom节点,正确的做法如下:

(1)

    

class Index extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            isRender:true
        };
        this.handleClock = this.handleClock.bind(this);   
        
    }
      handleClock(){
          this.setState({isRender: false});
      }
       render() {         
         return (
             <div className="wrapper">
                 {
                     this.state.isRender ? (
                        <Clock name="lalala" />
                    ) : null
                 }
                 <div onClick={this.handleClock}>移除</div>
             </div>
         );
      }

或者:

这样在卸载完组件的时候 会执行componentWillUnmount定义的代码;

例如有定时器的功能,如果不在卸载组件的时候清除clearInterval,就会一直进行setInterval的函数;

 

7:setState异步处理

先上个代码:

addClock(){
   this.setState({
        initNum:this.state.initNum+3
   });
   console.log(this.state.initNum);
}

我们在setState下面加了一个console,通过控制台可以发现,每次打印的值并不是当前输入的值,而是上一次输入的值,这是怎么回事呢? 

在setState中,这是一个异步处理的函数,并不是同步的,console在setState后立刻执行了,所以这时候状态还没有真正变更完,所以这里取到的状态仍旧是更新前的 
如果需要在更新状态后,再执行操作怎么办呢,setState还有第二个参数,接受一个callback,我们尝试将keyUp中代码改成这样

addClock(){
    this.setState({
        initNum:this.state.initNum+3
    },()=>{
        console.log(this.state.initNum);
    });
}

传入 setState 函数的第二个参数的作用是什么?

这时候log打印出来的只就是我们期望的内容,当每次状态更新成功后,都会调用传进去的callback函数。

因此总结如下: 


react中的setState特点: 


1.是异步操作函数;

 
2.组件在还没有渲染之前, this.setState 还没有被调用; 


3.批量执行 State 转变时让 DOM 渲染更快(相对比一个一个的setState的来的快)。

 

8:setState后面的会覆盖前面的

setState可以批量处理来提高它的性能,this.props 和 this.state的更新是异步的,不能依赖上一个state来计算下一个state的值

      addClock(){
          this.setState({
              initNum:this.state.initNum+1
          });
          this.setState({
              initNum:this.state.initNum+2
          });
          this.setState({
              initNum:this.state.initNum+3
          });
      }

会只执行最后一个函数 +3 ;

请使用第二种形式的 setState() 来接受一个函数而不是一个对象。 该函数将接收先前的状态作为第一个参数,将此次更新被应用时的props做为第二个参数:

this.setState(prevState => (
     {
         initNum: prevState.initNum + 1 
     } 
));
this.setState(prevState => ( 
     {
         initNum: prevState.initNum + 2 
     } 
))

这样的话就不会被覆盖,注意的是:(返回对象外侧需要()包括起来)

如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用return语句返回。

var sum = (num1, num2) => { return num1 + num2; }

由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号。

var getTempItem = id => ({ id: id, name: "Temp" });

9:props验证问题

从书籍和网上搜索到的信息 两种方式均无法验证props

      

## PropType
在定义一个通用组件或木偶组件时,我们最好声明这个组件接受的PropTypes。要注意的是,在React16之前,PropTypes是可以直接从React里获取的,从React16开始,PropTypes要从`prop-types这个模块中获取。

 

注意两点:

1:PropTypes出自的位置;

2:PropTypes要放在Clock的后面

 

 

10:带有参数的监听事件的写法:

<div onClick={()=>{
            this.handleEvnt('1')
}}>点击我1</div>
<div onClick={()=>{
            this.handleEvnt('2')
}}>点击我2</div>

错误写法:

<div onClick={this.handleEvnt('2')}>点击我2</div>

 

posted @ 2018-01-17 18:38  小猪冒泡  阅读(208)  评论(0编辑  收藏  举报