# Class组件详解
创建Class组件
两种方式创建class组件
ES5方式(过时)
import React from 'react'
const A = React.createClass({
render() {
return (
<div>hi</div>
)
}
})
exoprt default A
ES6方式
import React from 'react'
//建议能用React.PureComponent代替React.Component
class B extends React.Component{
constructor(props){
super(props)
}
render(){
return(
<div>hi</div>
)
}
}
export default B
Props(外部数据)
传入props给子组件
import React from 'react'
import ReactDOM from 'react-dom'
class Parent extends React.Component{
constructor(props){
super(props)
this.state = {name: 'jason'}
}
onClick = () =>{}
render(){
return (
<B name={this.state.name}
onClick={this.onClick}
>hi</B>
)
}
}
//外部被包装为一个对象
//{name:'jason',onClick:...,childer:'hi'}
//此处onClick是回调
Props外部数据初始化
class B extends React.Component{
constructor(props){
super(props)
}
render(){}
}
//this.props就是外部数据对象的地址了
Props外部数据读取
//通过this.props.xxx读取
//建议永远不要对props进行改写
class B extends React.Component{
constructor(){
super()
}
render(){
return(
<div onClick = {this.props.onClick}>
{this.props.name}
<div>
{this.props.children}
</div>
</div>
)
}
}
Props的作用
- 接受外部数据,只能读不能写,外部数据由父组件传递
- 接受外部函数,在恰当的时机调用该函数,该函数一般是父组件的函数
State(内部数据)
初始化State
class B extends React.Component{
constructor(){
super()
//初始化state
this.state = {
user: {
name: 'jason'
age: 18
}
}
}
}
读写state
读用this.state
this.state.xxx
写用 this.setState(???,fn),(注意:setState不会立即改变this.state,会在当前代码运行完后,再去更新this.state,从而触发UI更新)
//bug更少的写法
this.setState((state,props) => newState,fn) //fn会在写入成功后执行
写是会 shallow merge
setState会自动将新state与旧state进行一级合并
生命周期
生命周期钩子执行顺序图:
constructor() //在这里初始化state
shouldComponentUpdate() //return false阻止更新
render() //创建虚拟DOM
componentDidMount() //组件已出现在页面
componentDidUpdate() //组件已更新
componentWillUnmount() //组将将亡
constructor
用途:
- 初始化
props - 初始化state,但此时不能调用
setState - 用来
bind this
consttructor(){
/*...*/
this.onClick = this.onClick.bind(this)
}
//新语法
onClick = () =>{}
constructor(){/*....*/}
- 可不写
shouldComponentUpdate
用途:
- 返回
true表示不阻止UI更新 - 返回
false表示阻止UI更新
class App extends React.Component {
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>
APP
<div>
{this.state.n}
<button onClick={this.onClick}>+1</button>
</div>
</div>
)
}
}
问:shouldComponentUpdate有什么作用?
答:它允许我们手动判断是否要进行组件更新,我们可以根据应用场景灵活的设置返回值,以避免不必要的更新
render
用途:
- 展示视图:
return (<div>...</div>) - 只能有一个根元素
- 如果有两个根元素,就要用
<React.Fragment>包起来 <React.Fragment/>可以缩写成<></>
技巧:
render里面可以写if...else
class App extends React.PureComponent {
constructor(props) {
super(props)
this.state = {
n: 1
}
}
onClick = () => {
this.setState((state) => ({
n: state.n + 1
}))
}
render() {
let message
if (this.state.n % 2 === 0){
message = <div>偶数</div>
}else {
message = <span>奇数</span>
}
return (
<>
{message}
<button onClick={this.onClick}>+1</button>
</>
)
}
}
render里面可以写?:表达式
class App extends React.PureComponent {
constructor(props) {
super(props)
this.state = {
n: 1
}
}
onClick = () => {
this.setState((state) => ({
n: state.n + 1
}))
}
render() {
return (
<>
{this.state.n % 2 === 0 ?<div>偶数</div> : <span>奇数</span>}
<button onClick={this.onClick}>+1</button>
</>
)
}
}
render里面不能直接写for循环,需要用数组
class App extends React.PureComponent {
constructor(props) {
super(props)
this.state = {
n: 1,
array: [1,2,3],
}
}
onClick = () => {
this.setState((state) => ({
n: state.n + 1
}))
}
render() {
let result = []
for (let i = 0; i<this.state.array.length; i++){
result.push(this.state.array[i])
}
return result
}
}
render里面可以写array.map(循环),记住所有的循环里面都要加key
class App extends React.PureComponent {
constructor(props) {
super(props)
this.state = {
n: 1,
array: [1,2,3],
}
}
onClick = () => {
this.setState((state) => ({
n: state.n + 1
}))
}
render() {
return this.state.array.map(n => <span key={n}>{n}</span>)
}
}
conponentDidMount()
用途:
- 在元素插入页面后执行代码,这些代码依赖DOM
- 比如你想获取div的高度,就最好在这里
- 此处可以发起加载的AJAX请求(官方推荐)
- 首次渲染会执行此钩子
componentDidUpdate()
用途:
- 在视图更新后执行代码
- 此处可以发起
AJAX请求,用于更新数据 - 首次渲染不会执行钩子
- 在此处
setState可能会引起无线循环,除非放在if里 - 若shouldComponentUpdate返回false,则不会触发此钩子
componentWillUnmount
用途:
- 组件将要被移除页面然后被摧毁时执行代码
unmount过的组件你不会再次mount
举例:
- 如果在
componentDidMount里监听了window scroll,那么你就要在componentWillUnmount里取消监听 - 如果你在
componentDidMount里创建了Timer,那么你就要在componentWillUnmount里取消Timer - 如果你在
componentDidMount里创建了AJAX请求,那么你就要在componentWillUnmout里取消请求