-
案例一:不可变数据的力量
重要:不管是对象还是数组都是引用类型(保存的都是地址),意味着在内存里面会开辟一块内存空间,由指针指向。
添加数据与增加年龄:
import React, { Component, PureComponent } from "react";
export default class App extends PureComponent {
constructor(props) {
super(props);
this.state = {
friends: [
{
name: "lilei",
age: 18,
id: 1,
},
{
name: "zhangsan",
age: 8,
id: 2,
},
{
name: "lucy",
age: 33,
id: 3,
},
],
};
}
render() {
return (
<div>
<ul>
{this.state.friends.map((item, index) => {
return (
<li key={item.id}>
姓名:{item.name}
年龄:{item.age}
<button onClick={(e) => this.increase(index)}>年龄+1</button>
</li>
);
})}
</ul>
<button onClick={(e) => this.insertData()}>添加新数据</button>
</div>
);
}
insertData() {
// 不推荐直接push这样做,因为如果当前组件继承的是PureComponent,那么页面将无法更新,因为
// 在生命周期中shouldComponentUpdate(newProps,newState)比较时对比friends都是同一个内存地址
//错误示范开始
// this.state.friends.push({ name: "哈哈", age: 1, id: 88 });
// this.setState({
// friends: this.state.friends,
// });
// 错误示范结束
// 推荐下面的写法
const newFriends = [...this.state.friends]; //新开出地址
newFriends.push({ name: "哈哈", age: 1, id: 88 });
this.setState({
friends:newFriends
})
}
increase(index) {
console.log(index);
//错误示范开始
// this.state.friends[index].age +=1;
// this.setState({
// friends:this.state.friends
// })
//错误示范结束
//推荐下面的写法
const newFriends = [...this.state.friends];
newFriends[index].age += 1;
this.setState({
friends:newFriends
})
}
}
通常来说,我们的组件都可以直接继承PureComponent,这样可以优化部分性能
-
案例二:使用第三方events组件库传值
1.安装过程中如出现node版本不匹配:The engine “node“ is incompatible with this module..
// 步骤一:
yarn config set ignore-engines true
yarn add events
2.使用后记得销毁
import React, { PureComponent } from 'react'
import { EventEmitter } from 'events'
const eventBus = new EventEmitter();
export default class App extends PureComponent {
render() {
return (
<div>
<Home></Home>
<Header></Header>
</div>
)
}
}
export class Home extends PureComponent {
componentDidMount(){
eventBus.addListener("sayHello",this.handelLister)
}
componentWillUnmount(){
eventBus.removeListener("sayHello",this.handelLister)
}
handelLister(a,b){
console.log(a);
console.log(b);
}
render() {
return (
<div>home</div>
)
}
}
export class Header extends PureComponent {
render() {
return (
<div>
<div>Header</div>
<button onClick={e=>this.add()}>点击传值</button>
</div>
)
}
add(){
eventBus.emit("sayHello",123,"xiao")
}
}
-
案例三:使用ref操作DOM元素
import React, { PureComponent, createRef } from "react";
export default class App extends PureComponent {
constructor(props) {
super();
this.state = {};
this.titleRef = createRef(); // 方式二用到
this.titleEl = null ; // 方式三用到
this.classRef = createRef();
}
render() {
return (
<div>
<h2 ref="stringRef">hello react</h2>
<h2 ref={this.titleRef}>hello react</h2>
<h2 ref={(arg)=>this.titleEl=arg}>hello react</h2>
<button onClick={e=>this.changeText()}>改变文字</button>
<hr></hr>
<Counter ref={this.classRef}></Counter>
</div>
);
}
changeText(){
// 方式一:string--已经不推荐,放弃
this.refs.stringRef.innerHTML = "hello xxx"
// 方式二:对象--官方推荐
this.titleRef.current.innerHTML = "hello yyy"
// 方式三:函数--方式
this.titleEl.innerHTML = "hello zzz"
console.log(this.classRef.current);
}
}
export class Counter extends PureComponent{
constructor(props){
super()
this.state={
counter:1
}
}
render(){
return(
<div>
{this.state.counter}
<button onClick={e=>this.increase()}>couner里面的按钮</button>
</div>
)
}
increase(){
this.setState({
counter:this.state.counter+1
})
}
}
ref属性可以用于HTML元素,也可以用于class组件,但是不能在函数组件上使用ref属性,因为他们没有实例,但是:
- 某些时候,我们可能想要获取函数式组件中的某个DOM元素;
- 这个时候我们可以通过React.forwardRef,后面我们在hooks中如何使用ref