一. 创建一个类组件
//ES5
const A =React.createClass({
render(){
return (
<div>JSX</div>
)
}
})
//ES6
class Son extends React.Component {
constructor(props) {
super(props)
//必写
this.state{n:1}
//初始化实例的state属性
}
render(){
return (<div>{this.props.name}</div>)
//相当于以React.Component为原型生成一个实例,this指向此对象
}
}
二. props
上个例子中的props为外部传入的一个数据,其实是一个对象,我们需要在constructor初始化他,super的作用就是将prop的地址绑定到this.props上,所以props的地址是唯一的
2.1 如何将props传入子组件
class Parent extends React.Component{
constructor(props){
super(props)
//这里的props是上一级组件或者外部传入的
this.state={
name:'Parent'
}
}
onClick=()=>{}
render(){
return (
<B name={this.state.name}
onClick={this.onClick}>hello B</B>
)
}
}
实际上我们传入的props
{name:"Parent", onClick:this.onClick, children: ['hello B']}
然后我们来在B组件中接收并初始化props以及使用
class B extents React.Component{
constructor(props){
super(props)
}
render(){
return (
<div onClick={this.props.onClick}>
{this.props.name}
<div>
)
}
}
然后我们如何对pros进行修改呢
不允许对props进行修改
因为我们上面提到,this.props是一个与外部同地址的对象,所以props应该由外部进行更新
三. state与setState
state属性可以通过this.state.xx来访问,如果要修改则要通过setState()
this.setState( {
x:this.state.x+1
})
//他可以返回一个对象
this.setState((state) =>
({x: state.x + 1})
)
//也可以接受一个函数,返回一个对象
这两种方式的不同之处在于,前者如果连续调用则不会更新最新的state,因为他是一个异步操作,而后者则会在被调用时获取到最新的state
onClick = () => {
this.setState({
x: this.state.x + 1
})
this.setState({
x: this.state.x + 1
})
}
//如果点击一次,x只会加1
onClick2 = () => {
this.setState((state) =>
({x: state.x + 1})
)
this.setState((state) =>
({x: state.x + 1})
)
}
//点击之后,x会+1再+1
由于React的shallow merge,所以两次state更新会在更新UI的时候合并为一次
并且setState接受一个成功回调
this.setState(newState,fn)
onClick = () => {
this.setState({
x: this.state.x + 1
}, () =>
this.setState({
x: this.state.x + 1
})
)
}
//这样也能实现两次加1操作,但是他会触发两次state更新
如果想要观察上述变化可以使用一个已经弃用的props变化的钩子,他可以监听到props的变化,this.props为旧的数据,nextPorps指代更新后的props
componentWillReceiveProps(nextProps, nextContext) {
console.log('旧的')
console.log(this.props)
console.log('新的')
console.log(nextProps)
}