当前位置: 首页 > news >正文

React生命周期

生命周期-初始化

import React, { Component } from 'react'export default class App extends Component {componentWillMount(){console.log("第一次will mount")}componentDidMount(){console.log("第一次did mount")}render() {console.log("render")return ( <div></div>)}
}

componentWillMount是第一次上树前的最后一次修改状态

import React, { Component } from 'react'export default class App extends Component {state = {myname: 'switch',}componentWillMount() {console.log('第一次will mount',this.state.myname,document.getElementById('myname'))//第一次上树前 的最后一次修改状态this.setState({myname: 'Switch',})}componentDidMount() {console.log('第一次did mount', document.getElementById('myname'))}render() {console.log('render')return (<div><span id="myname">{this.state.myname}</span></div>)}
}

可以起到一个初始化数据的作用

import React, { Component } from 'react'export default class App extends Component {state = {myname: 'switch',}componentWillMount() {console.log('第一次will mount',this.state.myname,document.getElementById('myname'))//第一次上树前 的最后一次修改状态this.setState({myname: 'Switch',})}componentDidMount() {console.log('第一次did mount', document.getElementById('myname'))//数据请求axios//订阅函数的调用//setInterval// 基于创建完的dom进行初始化(BetterScroll)}render() {console.log('render')return (<div><span id="myname">{this.state.myname}</span></div>)}
}

初始化注意

import React, { Component } from 'react'export default class App extends Component {state = {myname: 'switch',}componentWillMount() {console.log('第一次will mount',this.state.myname,document.getElementById('myname'))//第一次上树前 的最后一次修改状态this.setState({myname: 'Switch',})}componentDidMount() {console.log('第一次did mount', document.getElementById('myname'))//数据请求axios//订阅函数的调用//setInterval// 基于创建完的dom进行初始化(BetterScroll)}render() {console.log('render')return (<div><span id="myname">{this.state.myname}</span></div>)}
}

之前那样写会报黄色的警告,因为优先级比较低,在执行过程中可能会被优先级较高的任务打断,改写之后就相当于告诉它,我是不安全的,就不会报警告了

Fiber 是 React 16 中引入的一个重大更新,它是一种新的协调算法,将渲染工作分割成多个小的任务单元,执行每个任务单元时可以被中断和恢复。在 React 的生命周期中,Fiber 的工作可以分为两个阶段:

  • Reconciliation 阶段:这个阶段 React 会找出需要更新的组件,并生成一个新的 Fiber 树。在这个阶段,React 会根据组件的 props 和 state 的变化,计算出哪些组件需要更新,并生成一个新的 Fiber 树。由于这个阶段是可以被中断和恢复的,所以 React 可以在这个阶段进行一些优化,例如暂停、终止或者重新排序任务。
  • Commit 阶段:这个阶段 React 会将新的 Fiber 树应用到 DOM 上,完成页面的更新。在这个阶段,React 会将新的 Fiber 树应用到 DOM 上,完成页面的更新。由于这个阶段是不可以被中断的,所以 React 会一次性完成所有的 DOM 操作。

Fiber 的引入,使得 React 的渲染过程更加高效和灵活。它可以让 React 在渲染过程中更好地利用浏览器的空闲时间,避免了长时间占用主线程导致的卡顿问题。同时,Fiber 还可以让 React 更好地处理异步操作和错误处理,提高了应用的性能和稳定性。

初始化案例

之前写的可以改写,把axios请求放到componentDidMount()

import React, { Component } from 'react'
import axios from 'axios'
import { extend } from 'lodash'export default class App extends Component {constructor() {super()this.state = {filmList: [],info: '',}}componentDidMount() {axios.get(`/cartData.json`).then((res) => {console.log(res.data.list)this.setState({filmList: res.data.list,})})}render() {return (<div>{this.state.info}{this.state.filmList.map((item) => (<FilmItemkey={item.id}{...item}onEvent={(value) => {// console.log("父组件接收",value)this.setState({info: value,})}}></FilmItem>))}<FilmDetail info={this.state.info}></FilmDetail></div>)}
}class FilmItem extends Component {render() {// console.log(this.props)let { name, poster, synopsis } = this.propsreturn (<div className="filmitem"><img src={poster} alt={name} /><h4>{name}</h4>{this.props.name}</div>)}
}class FilmDetail extends Component {render() {return <div className="filmdetail">{this.props.info}</div>}
}

这样改写没毛病

为什么一定要基于创建完的dom进行初始化呢?

有的库是纯js写的需要进行dom操作,不知道dom什么时候创建完它就没有办法工作

import React, { Component } from 'react'
import BetterScroll from 'better-scroll'export default class App extends Component {state = {list:["111","222","333","444","555","666","777","888","999","049","120","911","110"]}componentDidMount(){new BetterScroll("#wrapper")}render() {return (<div><div id='wrapper' style={{height:"200px",background:"yellow",overflow:"hidden"}}><ul>{this.state.list.map(item=>(<li key={item}>{item}</li>))}</ul></div></div>)}
}

在执行完之后就可以顺利的滚动了

生命周期-运行中

来看一段代码:

import React, { Component } from 'react'export default class App extends Component {state = {myname:"switch"}render() {console.log("render")return (<div><button onClick={()=>{this.setState({myname:"steam"})}}>click</button>{this.state.myname}</div>)}componentWillUpdate(){console.log("componentWillUpdate")}componentDidUpdate(){ console.log("componentDidUpdate")} 
}

搞一个滚动条:

import React, { Component } from 'react'
import axios from 'axios'
import BetterScroll from 'better-scroll'export default class App extends Component {state = {myname:"switch",list:[]}componentDidMount(){axios.get("/test.json").then(res=>{console.log(res.data.data.films)this.setState({list:res.data.data.films},()=>{// 访问真实domnew BetterScroll("#warpper")})})}render() {console.log("render")return (<div><button onClick={()=>{this.setState({myname:"steam"})}}>click</button><span id='myname'>{this.state.myname}</span><div id='warpper' style={{height:"100px",overflow:"hidden",background:"yellow"}}><ul>{this.state.list.map(item=><li key={item.filmId}>{item.name}</li>)}</ul></div></div>)}componentWillUpdate(){console.log("componentWillUpdate",document.getElementById("myname").innerHTML)}componentDidUpdate(){ console.log("componentDidUpdate",document.getElementById("myname").innerHTML)} 
}

componentDidMount中,当你调用new BetterScroll("#wrapper")时,此时this.state.list可能还没有被更新,也就是说#wrapper内的内容可能还没有完全渲染出来。BetterScroll需要在内容已经渲染好并且有足够高度差(内容高度大于容器高度)的情况下才能正常工作。

你可以尝试在setState的回调函数中初始化BetterScroll,这样可以确保在内容更新完成后再进行初始化

除了这一种方式还有别的方法吗?

这样也可以:

import React, { Component } from 'react'
import axios from 'axios'
import BetterScroll from 'better-scroll'export default class App extends Component {state = {myname:"switch",list:[]}componentDidMount(){axios.get("/test.json").then(res=>{console.log(res.data.data.films)this.setState({list:res.data.data.films})})}render() {console.log("render")return (<div><button onClick={()=>{this.setState({myname:"steam"})}}>click</button><span id='myname'>{this.state.myname}</span><div id='warpper' style={{height:"100px",overflow:"hidden",background:"yellow"}}><ul>{this.state.list.map(item=><li key={item.filmId}>{item.name}</li>)}</ul></div></div>)}componentWillUpdate(){console.log("componentWillUpdate",document.getElementById("myname").innerHTML)}componentDidUpdate(){ console.log("componentDidUpdate",document.getElementById("myname").innerHTML)new BetterScroll("#warpper")} 
}

在DidupState中可以接受到老的属性和老的状态

这样改可以避免被初始化多次:

import React, { Component } from 'react'
import axios from 'axios'
import BetterScroll from 'better-scroll'export default class App extends Component {state = {myname:"switch",list:[]}componentDidMount(){axios.get("/test.json").then(res=>{console.log(res.data.data.films)this.setState({list:res.data.data.films})})}render() {console.log("render")return (<div><button onClick={()=>{this.setState({myname:"steam"})}}>click</button><span id='myname'>{this.state.myname}</span><div id='warpper' style={{height:"100px",overflow:"hidden",background:"yellow"}}><ul>{this.state.list.map(item=><li key={item.filmId}>{item.name}</li>)}</ul></div></div>)}componentWillUpdate(){console.log("componentWillUpdate",document.getElementById("myname").innerHTML)}componentDidUpdate(prevProps,prevState){ console.log("componentDidUpdate",document.getElementById("myname").innerHTML)if(prevState.list.length === 0){new BetterScroll("#warpper")}new BetterScroll("#warpper")} 
}

每点一次都会更新,走render函数 

import React, { Component } from 'react'export default class App extends Component {state = {myname:"kerwin"}render() {return (<div><button onClick={()=>{this.setState({myname:"xiaoming"})}}>{this.state.myname}</button></div>)}
}

更不更新由一个函数来决定:

import React, { Component } from 'react'export default class App extends Component {state = {myname:"kerwin"}render() {return (<div><button onClick={()=>{this.setState({myname:"xiaoming"})}}>{this.state.myname}</button></div>)}shouldComponentUpdate(){return true     //应该更新// return false    //不应该更新}
}

想要提高性能应该在这里设置条件

import React, { Component } from 'react'export default class App extends Component {state = {myname: 'kerwin',}render() {console.log("render")return (<div><buttononClick={() => {this.setState({myname: 'xiaoming',})}}>{this.state.myname}</button></div>)}shouldComponentUpdate(nextProps, nextState) {if (this.state.myname !== nextState.myname) {return true //应该更新}return false //不应该更新}
}

这样一个一个状态的比还是太过于难以描述了,我们可以将对象转成字符串的比:

import React, { Component } from 'react'export default class App extends Component {state = {myname: 'kerwin',}render() {console.log("render")return (<div><buttononClick={() => {this.setState({myname: 'xiaoming',})}}>{this.state.myname}</button></div>)}shouldComponentUpdate(nextProps, nextState) {if (JSON.stringify(this.state) !== JSON.stringify(nextState)) {return true //应该更新}return false //不应该更新}
}

科文老师说有的把shouldComponentUpdate教程scu被人听成icu导致说了一大堆为公司鞠躬尽瘁死而后已的话,让我想起了肘学长简历上面写的什么喜欢打球可以接受高强度加班。

 import { curry } from 'lodash'
import React, { Component } from 'react'class Box extends Component{render(){return <div style={{width:"100px",height:"100px",border:this.props.current===this.props.index?'5px solid red':'1px solid gray',margin:"10px",float:'left'}}></div>}
}export default class App extends Component { state = {list:["00","01","02","03","04","05","06","07","08","09"],current:5} render() {return (<div><input type='number' onChange={(evt)=>{this.setState({current:Number(evt.target.value)})}}/><div style={{overflow:"hidden"}}>{this.state.list.map((item,index)=>{return <Box key={item} current={this.state.current} index={index}/>})}</div></div>)}}

真是太好玩了。可以跟着我的点击走

但是这份代码目前还存在着一定的问题

每一个小盒子都会被重新的渲染,我该如何优化?

这样进行更改,按条件来决定是否重新进行渲染:

 import { curry } from 'lodash'
import React, { Component } from 'react'class Box extends Component{shouldComponentUpdate(nextProps){if(this.props.current === this.props.index || nextProps.current === nextProps.index){return true}return false}render(){console.log("render")return <div style={{width:"100px",height:"100px",border:this.props.current===this.props.index?'5px solid red':'1px solid gray',margin:"10px",float:'left'}}></div>}
}export default class App extends Component { state = {list:["00","01","02","03","04","05","06","07","08","09"],current:5} render() {return (<div><input type='number' onChange={(evt)=>{console.log(evt.target.value)this.setState({current:Number(evt.target.value)})}} value={this.state.current}/><div style={{overflow:"hidden"}}>{this.state.list.map((item,index)=>{return <Box key={item} current={this.state.current} index={index}/>})}</div></div>)}}

不能直接对状态进行修改的原因就是,会通过this.state来看是否渲染,如果提前修改可能连第一次都不执行了

componentWillReceiveProps:父组件修改属性触发

import React, { Component } from 'react'class Child extends Component{render(){return <div>child</div>}componentWillReceiveProps(){console.log("componentWillReceiveProps")}
}export default class App extends Component {render() {return (<div><Child/></div>)}
}

子组件不论怎么作妖,这个componentWillReceiveProps都是不会理的

在父组件中做一次状态的更新也会引发孩子的生命周期的更新

import React, { Component } from 'react'class Child extends Component{render(){return <div>child</div>}componentWillReceiveProps(){console.log("componentWillReceiveProps")}
}export default class App extends Component {state={text:"111111111"}render() {return (<div>{this.state.text}<button onClick={()=>{this.setState({text:"2222222222"})}}>click</button><Child/></div>)}
}

这个componentWillReceiveProps存在的意义就是:可以最先获得父组件传来的属性,可以利用属性进行ajax或者逻辑处理,把属性转化成孩子自己的状态

import React, { Component } from 'react'class Child extends Component{state = {title:""}render(){return <div>child-{this.state.title}</div>}componentWillReceiveProps(nextProps){console.log("componentWillReceiveProps",nextProps)//最先获得父组件传来的属性,可以利用属性进行ajax或者逻辑处理//把属性转化成孩子自己的状态this.setState({title:nextProps.text + "kerwin"})}
}export default class App extends Component {state={text:"111111111"}render() {return (<div>{this.state.text}<button onClick={()=>{this.setState({text:"2222222222"})}}>click</button><Child text={this.state.text}/></div>)}
}

写一个实例:

import React, { Component } from 'react'
import axios from 'axios'export default class App extends Component {constructor(props){super(props)this.state = {type:1}}render() {return (<div><ul><lionClick={() => {this.setState({type: 1,})}}>正在热映</li><li onClick={() => {this.setState({type: 2,})}}>即将上映</li></ul><FilmList type={this.state.type}></FilmList></div>)}
}class FilmList extends Component {state={list:[]}//初始化-执行一次,只会更新,不会再度创建conponentDidMount(){// console.log(this.props.type)if(this.props.type === 1){//请求卖座正在热映的数据console.log("请求卖座正在热映的数据")axios({url:"https://m.maizuo.com/gateway?cityId=610100&pageNum=1&pageSize=10&type=1&k=4202475",headers:{'x-client-info':'{"a":"3000","ch":"1002","v":"5.2.1","e":"1741595630655347584860161","bc":"610100"}','x-host':'mall.film-ticket.film.list'}}).then(res=>{console.log(res.data.data.films)this.setState({list:res.data.data.films})})}else{//请求卖座即将上映的数据console.log("请求卖座即将上映的数据")axios({url:"https://m.maizuo.com/gateway?cityId=610100&pageNum=1&pageSize=10&type=2&k=7812849",headers:{'x-client-info':'{"a":"3000","ch":"1002","v":"5.2.1","e":"1741595630655347584860161"}','x-host':'mall.film-ticket.film.list'}}).then(res=>{console.log(res.data.data.films)this.setState({list:res.data.data.films})})}}UNSAFE_componentWillReceiveProps(nextProps){if(nextProps.type === 1){//请求卖座正在热映的数据console.log("请求卖座正在热映的数据")axios({url:"https://m.maizuo.com/gateway?cityId=610100&pageNum=1&pageSize=10&type=1&k=4202475",headers:{'x-client-info':'{"a":"3000","ch":"1002","v":"5.2.1","e":"1741595630655347584860161","bc":"610100"}','x-host':'mall.film-ticket.film.list'}}).then(res=>{console.log(res.data.data.films)this.setState({list:res.data.data.films})})}else{//请求卖座即将上映的数据console.log("请求卖座即将上映的数据")axios({url:"https://m.maizuo.com/gateway?cityId=610100&pageNum=1&pageSize=10&type=2&k=7812849",headers:{'x-client-info':'{"a":"3000","ch":"1002","v":"5.2.1","e":"1741595630655347584860161"}','x-host':'mall.film-ticket.film.list'}}).then(res=>{console.log(res.data.data.films)this.setState({list:res.data.data.films})})}}render() {return <ul>{this.state.list.map(item=><li key={item.filmId}>{item.name}</li>)}</ul>}
}

老声命周期存在一些问题:

(1) componentWillMount ,在ssr中 这个方法将会被多次调用, 所以会重复触发多遍,同时在这里如果绑定事件, 将无法解绑,导致内存泄漏 , 变得不够安全高效逐步废弃。

(2) componentWillReceiveProps 外部组件多次频繁更新传入多次不同的 props,会导致不必要的异步请求

(3) componetWillupdate, 更新前记录 DOM 状态, 可能会做一些处理,与componentDidUpdate相隔时间如果过 长, 会导致 状态不太信

生命周期-销毁

 如果销毁的话,绑在window窗口上的事件是不会消失的

import React, { Component } from 'react'export default class App extends Component {state = {isCreated:true}render() {return (<div><button onClick={()=>{this.setState({isCreated:!this.state.isCreated})}}>click</button>{this.state.isCreated&&<Child/>}</div>)}
}class Child extends Component{render(){return <div>child</div>}componentDidMount(){window.onresize=()=>{//窗口大小的监听console.log("resize")}}componentWillUnmount(){console.log("componentWillUnmount")}
}

可以这样清除绑在window上的事件:

import React, { Component } from 'react'export default class App extends Component {state = {isCreated:true}render() {return (<div><button onClick={()=>{this.setState({isCreated:!this.state.isCreated})}}>click</button>{this.state.isCreated&&<Child/>}</div>)}
}class Child extends Component{render(){return <div>child</div>}componentDidMount(){window.onresize=()=>{//窗口大小的监听console.log("resize")}this.timer=setInterval(()=>{console.log("1111")},1000)}componentWillUnmount(){console.log("componentWillUnmount")window.onresize = nullclearInterval(this.timer)       //清除定时器}
}

新生命周期-getDerivedStateFromProps

getDerivedStateFromProps 第一次的初始化组件以及后续的更新过程中(包括自身状态更新以及父传子) , 返回一个对象作为新的state,返回null则说明不需要在这里更新state

这个相当于代替了componentWillMount和componentWillupdate

import React, { Component } from 'react'export default class App extends Component {state = {myname:"kerwin",myage:100}static getDerivedStateFromProps(){//这是类方法不是对象方法console.log("getDrivedStateFromProps")return {//可以在这做最后一次的修改myname:"Kerwin"}}render() {return (<div><button onClick={()=>{this.setState({myname:"xiaoming"})}}>click</button>App -{this.state.myname} - {this.state.myage} </div>)}
}

这里更改了状态之后就是一直更改,然后一直被修改成大写字母开头的

初始化和更新都要做的逻辑可以合并在一起:

import React, { Component } from 'react'export default class App extends Component {state = {myname:"kerwin",myage:100}static getDerivedStateFromProps(nextProps,nextState){//这是类方法不是对象方法console.log("getDrivedStateFromProps",nextState)return {//可以在这做最后一次的修改myname:nextState.myname.substring(0,1).toUpperCase()+nextState.myname.substring(1)}}render() {return (<div><button onClick={()=>{this.setState({myname:"xiaoming"})}}>click</button>App -{this.state.myname} - {this.state.myage} </div>)}
}

静态方法里面不能调用this

案例

新生命周期和老生命周期不能共存

import React, { Component } from 'react'
import axios from 'axios'export default class App extends Component {constructor(props){super(props)this.state = {type:1}}render() {return (<div><ul><lionClick={() => {this.setState({type: 1,})}}>正在热映</li><li onClick={() => {this.setState({type: 2,})}}>即将上映</li></ul><FilmList type={this.state.type}></FilmList></div>)}
}class FilmList extends Component {state={list:[],type:1}//初始化-执行一次,只会更新,不会再度创建conponentDidMount(){// console.log(this.props.type)if(this.props.type === 1){//请求卖座正在热映的数据console.log("请求卖座正在热映的数据")axios({url:"https://m.maizuo.com/gateway?cityId=610100&pageNum=1&pageSize=10&type=1&k=4202475",headers:{'x-client-info':'{"a":"3000","ch":"1002","v":"5.2.1","e":"1741595630655347584860161","bc":"610100"}','x-host':'mall.film-ticket.film.list'}}).then(res=>{console.log(res.data.data.films)this.setState({list:res.data.data.films})})}else{//请求卖座即将上映的数据console.log("请求卖座即将上映的数据")axios({url:"https://m.maizuo.com/gateway?cityId=610100&pageNum=1&pageSize=10&type=2&k=7812849",headers:{'x-client-info':'{"a":"3000","ch":"1002","v":"5.2.1","e":"1741595630655347584860161"}','x-host':'mall.film-ticket.film.list'}}).then(res=>{console.log(res.data.data.films)this.setState({list:res.data.data.films})})}}//   UNSAFE_componentWillReceiveProps(nextProps){
//   }static getDerivedStateFromProps(nextProps,nextState){//这是类方法不是对象方法console.log("getDrivedStateFromProps",nextState)return {type:nextProps.type}
}componentDidUpdate(prevProps,prevState){console.log(this.state.type)if(this.state.type=== prevProps.type){return}if(this.state.type === 1){//请求卖座正在热映的数据console.log("请求卖座正在热映的数据")axios({url:"https://m.maizuo.com/gateway?cityId=610100&pageNum=1&pageSize=10&type=1&k=4202475",headers:{'x-client-info':'{"a":"3000","ch":"1002","v":"5.2.1","e":"1741595630655347584860161","bc":"610100"}','x-host':'mall.film-ticket.film.list'}}).then(res=>{console.log(res.data.data.films)this.setState({list:res.data.data.films})})}else{//请求卖座即将上映的数据console.log("请求卖座即将上映的数据")axios({url:"https://m.maizuo.com/gateway?cityId=610100&pageNum=1&pageSize=10&type=2&k=7812849",headers:{'x-client-info':'{"a":"3000","ch":"1002","v":"5.2.1","e":"1741595630655347584860161"}','x-host':'mall.film-ticket.film.list'}}).then(res=>{console.log(res.data.data.films)this.setState({list:res.data.data.films})})}}render() {return <ul>{this.state.list.map(item=><li key={item.filmId}>{item.name}</li>)}</ul>}
}

这样更改以后就会因为合并而不是点一次就执行一次了

新生命周期-getSnapshotBeforeUpdate

getSnapshotBeforeUpdate 取代了 componetWillUpdate ,触发时间为update发生的时候,在render之后 dom渲染之前返回一个值,作为componentDidUpdate的第三个参数

假设你要实现这样的一个功能:

import React, { Component } from 'react'export default class App extends Component {state = {mytext:"11111"}render() {console.log("render")return (<div>app<button onClick={()=>{this.setState({mytext:"22222"})}}>click</button>{this.state.mytext}</div>)}
//   componentWillUpdate(){
//     console.log("componentWillUpdate")
//   }
//需要注释掉,因为不能同时的使用componentDidUpdate(prevProps,prevState,value){console.log("componentDidUpdate",value)}getSnapshotBeforeUpdate(){console.log("getSnapshotBeforeUpdate")return 100}
}

这样就可以实现不变化的实现这个效果:

import React, { Component } from 'react'export default class App extends Component {state={list:[1,2,3,4,5,6,7,8,9]}myref = React.createRef()  getSnapshotBeforeUpdate(){//获取容器高度return this.myref.current.scrollHeight}componentDidUpdate(prevProps,prevState,value){this.myref.current.scrollTop += this.myref.current.scrollHeight-value}render() {return (<div><button onClick={()=>{this.setState({list:[...[11,12,13,14,15,16,17,18,19],...this.state.list]})}}>来邮件</button><h1>邮箱应用</h1><div style={{height:"200px",overflow:"auto"}} ref={this.myref}><ul>{this.state.list.map(item=><li key={item} style={{height:"100px",background:"yellow"}}>{item}</li>)}</ul></div></div>)}
}


http://www.mrgr.cn/news/94996.html

相关文章:

  • 可视化图解算法:链表中倒数(最后)k个结点
  • java-正则表达式-集合-泛型
  • 【数据库】SQL设计指南:如何编写性能优异的SQL
  • el-table的行向上移动向下移动,删除选定行
  • Diffie-Hellman 加密协议介绍 (DH,DHE,ECDHE)
  • docker(1) -- centos镜像
  • CAN及CANFD协议
  • 使用 Promise 和 .then() 解决同异步问题
  • Optiplex 3060 MT 电脑型号与尺寸
  • Qwen2.5-VL 开源视觉大模型,模型体验、下载、推理、微调、部署实战
  • C++基础: Rule of five/zero/three
  • 【数据结构】顺序表(附源码)
  • 《大语言模型》学习笔记(三)
  • 生成PDF文件:从html2canvas和jsPdf渲染到Puppeteer矢量图
  • SSL/TLS 和 SSH 区别
  • 2025最新!人工智能领域大模型学习路径、大模型使用、AI工作流学习路径
  • SpringCloud 学习笔记3(OpenFeign)
  • 【Netty】消息分发处理方式
  • 【数据库】掌握MySQL事务与锁机制-数据一致性的关键
  • MySQL :参数修改