组件性能优化
PureComponent
import React from "react"
class Home extends React.PureComponent {
constructor () {
super()
this.state = { age: 18 }
}
// shouldComponentUpdate(nextProps, nextState, nextContext) {
// if (this.state.age !== nextState.age) {
// return true
// }
// return false
// }
render() {
console.log('Home-render')
return (
<div>
Home
</div>
)
}
}
class App extends React.Component {
constructor () {
super()
this.state = {
num: 0
}
}
render() {
console.log('App-render')
return (
<div>
<Home />
<div>{this.state.num}</div>
<button onClick={() => this.showHome()}>App按钮</button>
</div>
)
}
showHome() {
this.setState({
num: this.state.num + 1
})
}
}
export default App
state注意点
永远不要直接修改state中的数据,如果要修改state中的数据,必须通过setState传递一个新的值
直接报问题,并且点击修改没有任何反应
- 以前的版本
- 可以改,但是在shouldComponentUpdate、React.PurComponent下不会触发更新
import React from 'react';
/*
1.state注意点
永远不要直接修改state中的数据
如果要修改state中的数据, 必须通过setState传递一个新的值
*/
class App extends React.PureComponent{
constructor(props){
super(props);
this.state = {
age : 0
}
}
render(){
console.log('App-render被调用');
return (
<div>
<p>{this.state.age}</p>
<button onClick={()=>{this.btnClick()}}>APP按钮</button>
</div>
)
}
/*
shouldComponentUpdate(nextProps, nextState, nextContext) {
console.log(this.state.age, nextState.age); // 0 1 //1 1
if(this.state.age !== nextState.age){
return true;
}
return false;
}
*/
btnClick(){
// 以下两种写法区别:
// 上面一种方式是设置了一个新的对象
// 下面这种方式是设置了以前的对象
// this.setState({
// age:this.state.age + 1
// })
this.state.age = this.state.age + 1;
this.setState(this.state);
}
}
export default App;
react获取元素
1.React中获取元素的方式
- 字符串
- 对象
- 回调函数
import React from "react"
class App extends React.Component {
constructor () {
super()
this.oPRef = React.createRef()
this.oDRef = null
}
render() {
console.log('App-render')
return (
<div>
{/* <div id={'box'}>p</div> */}
{/* <div ref={'box'}>p</div> */}
{/* <div ref={this.oPRef}>p</div> */}
<div ref={(arg) => { this.oDRef = arg }}>p</div>
<button onClick={() => this.showHome()}>App按钮</button>
</div>
)
}
showHome() {
console.log('点击了')
// 第一种获取方式: 传统方式(在react中不推荐)
// const box = document.getElementById('box')
// 第二种获取方式: 通过ref='字符串'
// const box = this.refs.box // refs被弃用
// 第三种方式:通过React.createRef()创建一个对象,然后将这个对象传递给ref (推荐)
// const box = this.oPRef.current
// 第四种获取方式:通过传递一个回调函数,然后保存回调函数参数的方式(推荐)
const box = this.oDRef
box.innerHTML = 'div'
}
}
export default App
注意点
- 获取原生元素,拿到的是元素本身
- 获取类组件元素,拿到的是组件实例对象
- 获取
函数组件元素,拿不到任何内容
import React from "react"
class Home extends React.PureComponent {
render() {
return (
<div>Home</div>
)
}
}
function About() {
return (
<div>About</div>
)
}
class App extends React.Component {
constructor () {
super()
this.oPRef = React.createRef()
this.oDRef = null
}
render() {
console.log('App-render')
return (
<div>
{/* <div id={'box'}>p</div> */}
{/* <div ref={'box'}>p</div> */}
{/* <div ref={this.oPRef}>p</div> */}
{/* <div ref={(arg) => { this.oDRef = arg }}>p</div> */}
{/* <Home ref={this.oPRef} /> */}
<About ref={this.oPRef} />
<button onClick={() => this.showHome()}>App按钮</button>
</div>
)
}
showHome() {
console.log('点击了')
// const box = document.getElementById('box')
// const box = this.refs.box // refs被弃用
// const box = this.oPRef.current
// const box = this.oDRef
// box.innerHTML = 'div'
const Home = this.oPRef.current // 类组件:组件实例;函数组件:null
console.log('Home', Home)
}
}
export default App
Ref转发
1.直接通过ref获取不到函数式组件
2.如果要获取的不是函数式组件本身,而是想获取函数式组件中的某个元素,可以使用Ref转发来获取
React.forwardRef
import React from "react"
class Home extends React.PureComponent {
render() {
return (
<div>Home</div>
)
}
}
// function About() {
// return (
// <div>About</div>
// )
// }
const About = React.forwardRef(function (props, myRef) { // myRef === my.oPRef
return (
<div>
<p>About</p>
<p ref={myRef}>About-myRef</p>
</div>
)
})
class App extends React.Component {
constructor () {
super()
this.oPRef = React.createRef()
this.oDRef = null
}
render() {
console.log('App-render')
return (
<div>
{/* <div id={'box'}>p</div> */}
{/* <div ref={'box'}>p</div> */}
{/* <div ref={this.oPRef}>p</div> */}
{/* <div ref={(arg) => { this.oDRef = arg }}>p</div> */}
{/* <Home ref={this.oPRef} /> */}
<About ref={this.oPRef} />
<button onClick={() => this.showHome()}>App按钮</button>
</div>
)
}
showHome() {
console.log('点击了')
// const box = document.getElementById('box')
// const box = this.refs.box // refs被弃用
// const box = this.oPRef.current
// const box = this.oDRef
// box.innerHTML = 'div'
const About = this.oPRef.current // 类组件:组件实例;函数组件:null
console.log('About', About)
}
}
export default App
受控组件
import React from "react"
class App extends React.PureComponent {
constructor (props) {
super(props)
this.state = {
name: 'study',
email: '123456@qq.com',
phone: '110'
}
}
render() {
return (
<form>
<input type="text" name={'name'} value={this.state.name} onChange={(e) => { this.change(e) }} />
<input type="text" name={'email'} value={this.state.email} onChange={(e) => { this.change(e) }} />
<input type="text" name={'phone'} value={this.state.phone} onChange={(e) => { this.change(e) }} />
</form>
)
}
change(e) {
console.log('e.target.name', e.target.name)
this.setState({
[e.target.name]: e.target.value
})
}
}
export default App
非受控组件
class App extends React.PureComponent {
constructor (props) {
super(props)
this.myRef = React.createRef()
}
render() {
return (
<form onSubmit={(e) => { this.submit(e) }}>
<input type="text" ref={this.myRef} />
<input type="submit" />
</form>
)
}
submit(e) {
e.preventDefault()
console.log('this.myRef', this.myRef.current.value)
}
}
高阶组件
import React from "react"
import { EventEmitter } from "events"
const AllContext = React.createContext({})
const { Provider, Consumer } = AllContext
const eventBus = new EventEmitter()
class Home extends React.PureComponent {
render() {
return (
<div>
<div>{this.props.dom}</div>
<div>{this.props.label}</div>
</div>
)
}
}
class Header extends React.PureComponent {
render() {
return (
<div>
<div>{this.props.dom}</div>
<div>{this.props.label}</div>
{
this.props.list.map(name => {
return <li key={name}>{name}</li>
})
}
</div>
)
}
}
function enhancedComponent(WrappedComponent) {
class AdvComponent extends React.PureComponent {
constructor (props) {
super(props)
this.state = {
list: []
}
}
componentDidMount() {
eventBus.addListener('update', this.update.bind(this))
}
componentWillUnmount() {
eventBus.removeListener('update', this.update.bind(this))
}
update(list) {
this.setState({
list: list
})
}
render() {
return (
<Consumer>
{
(value) => {
return (
<WrappedComponent {...value} {...this.props} {...this.state} />
)
}
}
</Consumer>
)
}
}
return AdvComponent
}
const HomeComponent = enhancedComponent(Home)
const HeaderComponent = enhancedComponent(Header)
class App extends React.PureComponent {
render() {
return (
<div>
<Provider value={{ dom: 'DOM' }}>
<HomeComponent label={'Home'}></HomeComponent>
<hr />
<HeaderComponent label={'Header'}></HeaderComponent>
</Provider>
<button onClick={this.btnClick.bind(this)}>展示数据</button>
</div>
)
}
btnClick() {
eventBus.emit('update', ['好好', '学习', '天天'])
}
}
export default App
class Info extends React.PureComponent{
render() {
return (
<div>用户信息</div>
)
}
}
class Login extends React.PureComponent{
render() {
return (
<div>用户登录</div>
)
}
}
function EnhancedComponent (WrappedComponent) {
class Authority extends React.PureComponent{
render() {
if(this.props.isLogin){
return <Info/>
}else{
return <Login/>
}
}
}
return Authority;
}
const AuthorityInfo = EnhancedComponent(Info);
class App extends React.PureComponent{
constructor(props){
super(props);
}
render(){
return (
<AuthorityInfo isLogin={true}/>
)
}
}
Fragment
import React from "react"
class Home extends React.PureComponent {
constructor (props) {
super(props)
this.state = {
heroList: ['张大', '王大', '李达']
}
}
render() {
return (
// this.state.heroList.map(name => {
// return (
// <p key={name}>{name}</p>
// )
// })
// <>
// {
// this.state.heroList.map(name => {
// return (
// <p key={name}>{name}</p>
// )
// })
// }
// </>
<>
{
this.state.heroList.map(name => {
return (
<React.Fragment key={name}>
<p>{name}</p>
</React.Fragment>
)
})
}
</>
)
}
}
class App extends React.PureComponent {
render() {
return (
<>
<p>12</p>
<Home />
</>
)
}
}
export default App