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
,在render
中this.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>