创建class组件
ES6
import React from 'react'
class B extends React.Component
{
constructor(props);
super(props);
}
render(){
return (
<div>hi</div>
)
}
export default B;
Props(外部数据)
prop外部数据
- 传入props给B组件
class Parent extends React.Component{
constructor(props){
super(props)
this.state = { name:'mamami'}
}
onClick = () => {}
render(){
return <B name = {this.state.name} onClick={this.onClick}>hi</B>
}
}
//外部数据被包装为一个对象
//{name: 'mamami',onClick:...,children:'hi'}
//此处的onClick是一个回调
初始化:
class B extends React.Component{
constructor(props){
super(props);
}
render(){}
效果: 这么做了之后this.props就是外部数据对象的地址了
读取
class B extends React.Component{
constructor(props){
super(props);
}
render(){
return <div onClick={this.props.onClick}>{this.props.children}</div>
<div> { this.props.children}</div>
}
}// 通过 this.props.xxx读取
写props
- 改props的值(一个地址)
- this.props ={/另一个对象/}
- 不要写这样的代码,没有意义
- 理由:既然是外部数据,就不因该在内部修改。
原则
- 因该由数据的主人来修改。
相关钩子函数
comppnentWillReceiveProps钩子
- 当组件接收新的props,会触发此钩子
props的作用
接受外部数据
- 只能读不能写
- 外部数据由父组件传递
接受外部函数
- 在恰当的时机,调用改函数
- 该函数一般是父组件的函数
State & setState (内部数据)
初始化State
class B extends React.Component{
constructor(props){
super(props);
this.state = {
user: {name:'mamami',age:200}
}
}
render(){*/ ... */ }
}
读写State
- 读用this.stat
- this.state.xxx.yyy.nnn
- 写用this.setState(???,fn)
- this.setState(newState,fn)
- 注意se不会立刻改变this,Stat.state,会在当前代码运行完后,再去更新this.state,从而触发ui更新
- this.setState((state,props)=>newState,fn)
- fn会在写入成功后执行
写时会shallow merge
- setState会自动将新state与旧state进行一级合并 注意: 修改this.state的属性值this.state.n+=1不建议使用
生命周期
类比如下代码
// 这是div的create/construct过程
div.textContent = 'hi'
// 这时初始化state
document.body.appendChild(div)
//这是div的mount过程
div.textContent = "h2"
//这是div的update过程
div.remove()
//这是div的unmount过程
同理
- react组件也有这些
函数列表
- constructor()-在这里初始化state
- shouldComponentUpdate()-return false阻止更新
- render() -创建虚拟DOM
- componentDidMount() -组件已经出现在页面
- componentDidUpdate() -组件已经更新
- componentWillUnmount() -组件即将消失
constructor
- 用途
- 初始化props
- 初始化state,但此时不能调用setState
- 用来写bind this
constructor(){
/* 其他代码略*/
this.onClick =this.onClick.bind(this)
}
可以用新语法代替
onclick = () =>{}
constructor(){/**/}
shouldComponentUpdate
用途
- 返回true表示不阻止ui更新
- 返回false表示阻止ui更新 代码
class App extends React.Component{//这里可以改为React.PureComponent就可以不适用这个钩子监听了
constructor(props) {
super(props);
this.state = {
n: 1,
}
}
onClick= () =>{this.setState(state=>({
n : state.n + 1
}))
this.setState(state=>({
n : state.n - 1
}))
};
shouldComponentUpdate(nextProps, nextState, nextContext) {
return nextState.n !== this.state.n;
}
render() {
console.log("render了一次")
return (
<div>
{this.state.n}
<button onClick={this.onClick}>+1</button>
</div>
)
}}
render
- 用途
- 展示视图
return (<div>..</div>) - 只能由一个根元素
- 如果由两个根元素就要用<React.Fragment>包起来
- <React.Fragment/>可以缩写为<></>
技巧
- render 里面可以写if..else
- render里面可以写?:表达式
- render里面不能直接写for循环,需要用数组
- render里面可以写array.map(循环)
componentDidMont()
用途
- 在元素插入页面后执行代码,这些代码依赖dom
- 比如你想获取div的高度,就最好在这里写
- 此处可以发起加载数据的AJAX请求(官方推荐)】
- 首次渲染会执行该钩子 具体参数看官方文档
componentDidUpdate()
- 用途
- 在视图更新后执行代码
- 此处也可以发AJAX请求,用于更新数据|
- 首次渲染不会执行该钩子
- 在此处setState可能会引起无线循环,除非放在if里
- 若shouldCom...Update返回false,则不会触发此钩子 参数看文档
ComponentWillUnmount
用途
- 组件将要被移除页面然后被销毁时执行的代码
举例
- 如果你在c...DidMount里面监听了window scroll,那么你就要在c..willUnmount里面取消监听