一. class 组件创建方式
import React from 'react';
class B extends React.Component {
constructor(props){
super(props);
}
render(){
return (
<div>hi</div>
)
}
}
二. Props 外部数据
class Parent extends React.Component {
constructor(props){
super(props)
this.state = {name:'frank'}
}
onClick = ()=>{}
render(){
return <B name={this.state.name} onClick={this.onClick}>hi</B>
} // 这里的name和onClick就是props,来源是从this.state来的,是从外部来的作为props
}
// props如何初始化,这样子做了之后this.props就是外部数据的对象地址了
class B extends React.Component {
constructor(props){
super(props);
}
render(){
}
}
// 读取props
class B extends React.Component {
constructor(props){
super(props);
}
render(){
return <div onClick={this.props.onClick}>
{this.props.name}
<div>
{this.props.children}
</div>
</div>
}
}
// 不能去写props,外部数据应该由外部更新
三. componentWillReceiveProps 的作用
- 接收外部数据,只能读不能写,外部呀数据由父组件传递
- 接受外部函数,在恰当的时机调用该函数,该函数一般是父组件的函数
import React from 'react';
class App extends React.Component {
constructor(props){
super(props)
this.state = {x : 1}
}
onClick = () => {
this.setState({
x: this.state.x + 1
})
}
render(){
return (
<div className="App">
App <button onClick={this.onClick}>+1</button>
<B name={this.state.x}/>
</div>
);
}
}
class B extends React.Component {
UNSAFE_componentWillReceiveProps(newProps, nextContext) {
console.log('旧的 props')
console.log(this.props)
console.log('props变化了')
console.log('新的p props')
console.log(newProps)
}
render(){
return (
<div>{this.props.name}</div>
)
}
}
export default App;
四. State & setState 内部数据
- 初始化 State
class B extends React.Component{
constructor(props){
super(props);
this.state = {
user: {name:'frank', age:187}
}
}
render(){
}
}
- setState 的两种方式,推荐写成函数的形式,一般就用第一个参数,还有第二个参数接受成功之后的回调函数,另外写 state 的时候会进行一级合并(shallow merge)
onClick = () => {
this.setState({
x: this.state.x + 1
})
this.setState({
x: this.state.x + 1
})
}
onClick2 = () => {
this.setState((state)=>({x:state.x+1}))
this.setState((state)=>({x:state.x+1}))
}
五. 生命周期
let div = document.createElement('div')
// 这是div的 create/construct 过程
div.textContent = 'hi'
// 这是初始化state
document.body.appendChild(div)
// 这是div的mount过程
div.textContent = 'hi2'
// 这是div的update过程
div.remove()
// 这是div的unmount过程
- 函数列表,以下是常用的
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更新
- 示例见下页
- 面试常问: shouldComponentUpdate有什么用?
- 答: 它允许我们手动判断是否要进行组件更新,我们可以根据应用场景灵活地设置返回值,以避免不必要的更新
- React.PureComponent会对state和props进行浅对比,就不需要shouldComponentUpdate了
-
render的用途
- 展示视图,
// return 对应的对象是不是一个dom元素, 而是一个表示dom元素的对象, 我们称其虚拟dom return (<div>...</div>)
- 只能有一个根元素
用React.Fragment做占位,也可以写成<></>,两者等价
-
技巧
// render里面可以写if...else // 可以写?: // 不能直接写for,需要用数组 // 可以写array.map import React from 'react'; class App extends React.PureComponent { constructor(props){ super(props) this.state = { n:1 } } onClick= ()=>{ this.setState(state=> ({ n: state.n+1 })) } render(){ console.log('render了一次') let message if(this.state.n % 2 === 0 ) { message = <div>偶数</div> } else { message = <span>奇数</span> } return ( <> {message} <button onClick={ this.onClick }>+1</button> </> ) } } export default App; // 循环的写法 render() { return this.state.array.map(n=><span key={n}>{n}</span>) }
-
componentDidMount()的用途
- 在元素插入页面后执行代码,这些代码依赖DOM
- 比如你想获取div的高度,就最好在这里写
- 此处可以发起加载数据的AJAX请求(官方推荐)
-
首次渲染会执行此钩子
componentDidMount() { const div = document.getElementById('xxx') const {width} = div.getBoundingClientRect() // console.log(width) this.setState({width}) } render(){ return( <div id='xxx'>Hello World, {this.state.width} </div> ) }
-
也可以用ref来做
import React from 'react'; class App extends React.PureComponent { constructor(props){ super(props) this.state = { n:1, width: undefined } this.divRef = React.createRef() } onClick= ()=>{ this.setState(state=> ({ n: state.n+1 })) } componentDidMount() { const div = this.divRef.current const {width} = div.getBoundingClientRect() // console.log(width) this.setState({width}) } render(){ return( <div ref={this.divRef}>Hello World, {this.state.width}px </div> ) } } export default App;
-
componentDidUpdate()的作用
- 在视图更新后执行代码
- 此处也可以发起AJAX请求,用于更新数据(看文档)
- 首次渲染不会执行此钩子
- 在此处setState可能会引起无限循环,除非放在if里
- 若componentDidUpdate返回false,则不触发此钩子
-
componentWillUnmount的用途
- 组件将要被移除页面然后被销毁时执行的代码
- unmount过的组件不会再次mount
- 举例:
如果你在componentDidMount里面监听了window scroll 那么就要在componentWillUnmount的用途里面取消监听 如果你在componentDidMount里面创建了Timer 那么就要在componentWillUnmount里面取消Timer 如果你在componentDidMount里面创建了AJAX请求,这种情况比较特殊,数据还没回来你就死了 那么就要在componentWillUnmount里面取消请求
-
总结:
- 能用函数组件就用函数组件,能用purecomponent就用purecomponent,最后不行采用 react.component
- 生命周期函数
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。