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 (); }}class Index extends React.Component { constructor(props) { super(props); this.state = { }; this.handle = this.handle.bind(this); } handle() { alert('你看你看~'); } render() { return (click me{this.props.name}
); }}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 (); }}export default Index;这是首页
welcome组件:
import React from 'react';import UserInfo from './UserInfo.jsx';class Welcome extends React.Component { render() { return (); }}export default Welcome;click me--{this.props.name}
UserInfo 组件:
import React from 'react';class UserInfo extends React.Component { render() { return (); }}export default UserInfo;我的年龄是{this.props.age}
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 (); } 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 ({ this.state.isRender ? (); }) : null } 移除
或者:
这样在卸载完组件的时候 会执行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:带有参数的监听事件的写法:
{ this.handleEvnt('1')}}>点击我1{ this.handleEvnt('2')}}>点击我2
错误写法:
点击我2