react生命周期
-
生命周期回调函数----生命周期钩子函数-----生命周期函数
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>引出生命周期.</title> </head> <body> <!-- 准备一个容器 --> <div id="test"></div> <!-- 引入react核心库 --> <script src="https://cdn.bootcdn.net/ajax/libs/react/18.2.0/umd/react.development.min.js"></script> <!-- 引入react-dom, 用于支持react操作dom, 需要在核心库之后引入 --> <script src="https://cdn.bootcdn.net/ajax/libs/react-dom/18.2.0/umd/react-dom.development.min.js"></script> <!-- 引入babel.js,用于将jsx转化为js --> <script src="https://cdn.bootcdn.net/ajax/libs/babel-standalone/7.18.7/babel.min.js"></script> <!-- 引入prop-types --> <script src="https://cdn.bootcdn.net/ajax/libs/prop-types/15.8.1/prop-types.min.js"></script> <script type="text/babel"> class Life extends React.Component { state = { opacity: 0 }; death = () => { // 卸载组件 ReactDOM.unmountComponentAtNode(document.getElementById('test')) } // 组件挂载完毕 componentDidMount() { this.timer = setInterval(() => { let { opacity } = this.state; opacity -= 0.1; console.log(opacity, 'opacity==='); if(opacity <= 0) opacity = 1; this.setState({ opacity }) }, 200); } // 组件即将卸载 componentWillUnmount() { clearInterval(this.timer) } render() { return ( <div> <h2 style={{ opacity: this.state.opacity }}>react学不会怎么办?</h2> <button onClick={this.death}>不活了</button> </div> ) } } ReactDOM.render(<Life />, document.getElementById('test')) </script> </body> </html>
旧的生命周期
更新线路
-
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>react生命周期(旧)</title> </head> <body> <!-- 准备一个容器 --> <div id="test"></div> <!-- 引入react核心库 --> <script src="https://cdn.bootcdn.net/ajax/libs/react/18.2.0/umd/react.development.min.js"></script> <!-- 引入react-dom, 用于支持react操作dom, 需要在核心库之后引入 --> <script src="https://cdn.bootcdn.net/ajax/libs/react-dom/18.2.0/umd/react-dom.development.min.js"></script> <!-- 引入babel.js,用于将jsx转化为js --> <script src="https://cdn.bootcdn.net/ajax/libs/babel-standalone/7.18.7/babel.min.js"></script> <!-- 引入prop-types --> <script src="https://cdn.bootcdn.net/ajax/libs/prop-types/15.8.1/prop-types.min.js"></script> <script type="text/babel"> /* 1.初始化阶段:由ReactDOM.render触发---初次渲染 1.constructor() 2.componentWillMount() 3.render() 4.componentDidMount() ===> 常用 一般在这个钩子里做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息 2.更新阶段:由组件内部this.setState()或父组件render触发 1.shouldComponentUpdate() 2.componentWillUpdate() 3.render() 4.componentDidUpdate() 3.卸载组件:由ReactDOM.unmountComponentAtNode()触发 1.componentWillUnmount() ===> 常用 一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅 */ // 创建组件 class Count extends React.Component { constructor(props) { console.log('Count-constructor'); super(props); // 初始化状态 this.state = { count: 0 } } // 组件将要挂载的钩子 componentWillMount() { console.log('Count---componentWillMount'); } // 组件挂载钩子 componentDidMount() { console.log('Count---componentDidMount'); } // 组件即将卸载 componentWillUnmount() { console.log('Count---componentWillUnmount'); } // 控制组件更新的‘阀门’ (setState后,判断是否更新组件) shouldComponentUpdate() { // 此钩子必须有返回值 true/false true:更新组件 false:不更新组件 console.log('Count---shouldComponentUpdate'); return true; } // 组件将要更新的钩子 componentWillUpdate() { console.log('Count---componentWillUpdate'); } // 组件更新完毕的钩子 componentDidUpdate() { console.log('Count---componentDidUpdate'); } add = () => { let { count } = this.state; count += 1; this.setState({ count }) } // 销毁组件 death = () => { ReactDOM.unmountComponentAtNode(document.getElementById('test')) } // 强制更新 force = () => { this.forceUpdate() } render() { console.log('Count---render'); const { count } = this.state; return ( <div> <h2>当前的求和是{count}</h2> <button onClick={this.add}>点我+1</button> <button onClick={this.death}>销毁</button> <button onClick={this.force}>不更改任何状态中的数据,强制更新</button> </div> ) } } class A extends React.Component { state = { carName: '奔驰' } changeCar = () => { this.setState({ carName: '奥拓' }) } render() { return ( <div> <h1>我是A组件</h1> <button onClick={this.changeCar}>换车</button> <B carName={this.state.carName} /> </div> ) } } class B extends React.Component { // 将要接收props钩子 componentWillReceiveProps(props) { // 这个钩子有个坑 // 第一次接收props时 不调用此钩子 // 第一次后,接收的props才调用此钩子 console.log('B---componentWillReceiveProps', props); } // 组件是否更新 shouldComponentUpdate() { console.log('B---shouldComponentUpdate'); return true; } // 组件将要更新的钩子 componentWillUpdate() { console.log('B---componentWillUpdate'); } // 组件更新完毕的钩子 componentDidUpdate() { console.log('B---componentDidUpdate'); } render() { console.log('B---render'); return ( <div> <h1>我是B组件,接收的车是:{this.props.carName}</h1> </div> ) } } // 渲染组件 ReactDOM.render(<A />, document.getElementById('test')) </script> </body> </html>
新的生命周期
与旧的生命周期相比,
1.componentWillMount、componentWillUpdate、componentWillReceiveProps 这三个生命周期前应该加上UNSAFE_前缀
2.componentWillMount、componentWillReceiveProps、componentWillUpdate以后会移除
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>react生命周期(新)</title> </head> <body> <!-- 准备一个容器 --> <div id="test"></div> <!-- 引入react核心库 --> <script src="https://cdn.bootcdn.net/ajax/libs/react/18.2.0/umd/react.development.min.js"></script> <!-- 引入react-dom, 用于支持react操作dom, 需要在核心库之后引入 --> <script src="https://cdn.bootcdn.net/ajax/libs/react-dom/18.2.0/umd/react-dom.development.min.js"></script> <!-- 引入babel.js,用于将jsx转化为js --> <script src="https://cdn.bootcdn.net/ajax/libs/babel-standalone/7.18.7/babel.min.js"></script> <!-- 引入prop-types --> <script src="https://cdn.bootcdn.net/ajax/libs/prop-types/15.8.1/prop-types.min.js"></script> <script type="text/babel"> /* 1.初始化阶段:由ReactDOM.render触发---初次渲染 1.constructor() 2.getDerivedStateFromProps() 3.render() 4.componentDidMount() 2.更新阶段:由组件内部this.setState()或父组件render触发 1.getDerivedStateFromProps() 2.shouldComponentUpdate() 3.render() 4.getSnapshotBeforeUpdate() 5.componentDidUpdate() 3.卸载组件:由ReactDOM.unmountComponentAtNode()触发 1.componentWillUnmount() */ // 创建组件 class Count extends React.Component { constructor(props) { console.log('Count-constructor'); super(props); // 初始化状态 this.state = { count: 0 } } // 从props得到派生状态 static getDerivedStateFromProps(props, state) { // 只有组件的状态完全取决于props,自身定义的state将会失效,可以用这个钩子,开发中一般不会用到,了解即可 console.log('Count-getDerivedStateFromProps', props, state); // return props; // return { count: 0 }; return null; } // 组件挂载钩子 componentDidMount() { console.log('Count---componentDidMount'); } // 组件即将卸载 componentWillUnmount() { console.log('Count---componentWillUnmount'); } // 控制组件更新的‘阀门’ (setState后,判断是否更新组件) shouldComponentUpdate() { // 此钩子必须有返回值 true/false true:更新组件 false:不更新组件 console.log('Count---shouldComponentUpdate'); return true; } // 在更新之前获取快照 getSnapshotBeforeUpdate() { console.log('Count---getSnapshotBeforeUpdate'); return null; } // 组件更新完毕的钩子 componentDidUpdate(preProps, preState, snapShotValue) { // preProps 先前的props值;preState 先前的状态值;snapShotValue 快照值(getDerivedStateFromProps的返回值); console.log('Count---componentDidUpdate', preProps, preState, snapShotValue); } add = () => { let { count } = this.state; count += 1; this.setState({ count }) } // 销毁组件 death = () => { ReactDOM.unmountComponentAtNode(document.getElementById('test')) } // 强制更新 force = () => { this.forceUpdate() } render() { console.log('Count---render'); const { count } = this.state; return ( <div> <h2>当前的求和是{count}</h2> <button onClick={this.add}>点我+1</button> <button onClick={this.death}>销毁</button> <button onClick={this.force}>不更改任何状态中的数据,强制更新</button> </div> ) } } // 渲染组件 ReactDOM.render(<Count count="199" />, document.getElementById('test')) </script> </body> </html>
getSnapshotBeforeUpdate钩子的使用场景
此钩子返回值是 componentDidUpdate钩子的第三个参数
可以用getSnapshotBeforeUpdate拿到更新前的dom数据,在更新后做一些事情
比如,有一个持续新增的新闻列表,每次新增新闻,滚动条都会把最新的一条展示在最顶部,可以利用上面的两个钩子,使得滚动条一直保持在原来的内容展示区域;
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>getSnapshotBeforeUpdate使用场景.html</title> <style> .list{ width: 200px; height: 150px; background: skyblue; overflow: auto; } .news{ height: 30px; } </style> </head> <body> <!-- 准备一个容器 --> <div id="test"></div> <!-- 引入react核心库 --> <script src="https://cdn.bootcdn.net/ajax/libs/react/18.2.0/umd/react.development.min.js"></script> <!-- 引入react-dom, 用于支持react操作dom, 需要在核心库之后引入 --> <script src="https://cdn.bootcdn.net/ajax/libs/react-dom/18.2.0/umd/react-dom.development.min.js"></script> <!-- 引入babel.js,用于将jsx转化为js --> <script src="https://cdn.bootcdn.net/ajax/libs/babel-standalone/7.18.7/babel.min.js"></script> <!-- 引入prop-types --> <script src="https://cdn.bootcdn.net/ajax/libs/prop-types/15.8.1/prop-types.min.js"></script> <script type="text/babel"> class NewsList extends React.Component { state = { newsArr: [] } componentDidMount() { setInterval(() => { const { newsArr } = this.state; const news = '新闻' + (newsArr.length + 1); this.setState({ newsArr: [ news, ...newsArr ] }) }, 1000); } getSnapshotBeforeUpdate() { return this.refs.list.scrollHeight; } componentDidUpdate(preProps, preState, snapshotValue) { console.log(snapshotValue, 'snapshotValue==='); this.refs.list.scrollTop += this.refs.list.scrollHeight - snapshotValue; } render() { return ( <div className="list" ref="list"> { this.state.newsArr.map((n, index) => { return <div key={index} className="news">{n}</div> }) } </div> ) } } // 渲染组件 ReactDOM.render(<NewsList />, document.getElementById('test')) </script> </body> </html>
-