对⼀个问题的研究,尝试⽤⻩⾦圈法则来分析。
⼀句话概况:React
使⽤了 shallowCompare
来决定是否应该重新渲染⼀个组件。
要理解 shallowCompare
,我们⾸先需要知道 JavaScript
是如何处理对象引⽤的。让我们来看 ⼀个例⼦:
const people = [{ name: "mary", age: 20 }, { name: "john", age: 30 }];
const john = people[1];
const jonhClone = { name: "john", age: 30 };
console.log(john === people[1]) // true
console.log(john === jonhClone) // false
people[1].age = 31;
console.log(john) // { name: "john", age: 31 }
console.log(jonhClone) // { name: "john", age: 30 }
johnClone
的 name
和 age
与 john
相同,但他们不是同⼀个⼈。当我们声明 john = people[1]
, 我们没有拷⻉ people[1]
的 name
和 age
给 john
,两个变量都指向同⼀个对象作为引⽤。
现在我们来看⼀个 shallowCompare
的例⼦:
let oldProps = null;
function shallowCompare (props){
if(props !== oldProps) console.log(props);
oldProps = props;
}
const mary = { name: "mary", age: 20 };
const john = { name: "john", age: 30 };
shallowCompare(mary) // prints -> { name: "mary", age: 20 }
shallowCompare(john) // prints -> { name: "john", age: 30 }
john.age = 31;
shallowCompare(john) // will not print!
如果我们想打印 john
的更新,我们需要浅拷⻉它。这样⼀来,shallowCompare
就会知道道具发⽣了变化。
let oldProps = null;
function shallowCompare (props){
if(props !== oldProps) console.log(props);
}
const john = { name: "john", age: 30 };
shallowCompare(john) // prints -> { name: "john", age: 30 }
const johnClone = {...john};
johnClone.age=31;
shallowCompare(johnClone) // prints -> { name: "john", age: 31 }
React
使⽤同样的原则来避免不必要的组件重渲染。
class People extends Component {
constructor(props) {
super(props);
this.state = {
people:[{ name: "mary", age: 25 }, { name: "john", age: 30 }]
};
}
updateJohnAge = ()=>{
const people = [...this.state.people];
people[1].age=31;
this.setState({people});
//This will not work.
//People is a new array, but john is the same object
}
render() {
return (
<div>
<Person person={this.state.people[1]}></Person>
<button onClick={this.updateJohnAge}>Set john age to 31</button>
</div>
);
}
}
class Person extends Component {
render() {
const { person } = this.props;
return (
<div>
<p>name: {person.name}</p>
<p>age: {person.age}</p>
</div>
);
}
}
如果我们点击按钮,组件将不会呈现 john
的更新,因为 people[1]
是上次的同⼀个引⽤。为此,没有改变 john
。我们需要在之前克隆 john
,然后更新数组。
updateJohnAge = () =>{
const people = [...this.state.people];
const johnClone = {...people[1]};
johnClone.age = 31;
people[1] = johnClone;
this.setState({people});
//This will work.
}
要知道,我们并没有拷⻉ people[0] (mary)
。Immutable
并不意味着我们要详尽地克隆所有对象的 ramifications
。这将不会很有效率。我们只需要通过我们改变的路径来创建新的引⽤。
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8