shouldComponentUpdate()
is one of React lifecycle Methods. Use shouldComponentUpdate()
to let React know if a component’s output is not affected by the current change in state or props. The default behavior is to re-render on every state change, and in the vast majority of cases you should rely on the default behavior. (link)
In Vue, a component’s dependencies are automatically tracked during its render, so the system knows precisely which components actually need to re-render when state changes. Each component can be considered to have shouldComponentUpdate()
automatically implemented for you, without the nested component caveats. (link, link)
Oops, Vue has already done the work for us, that’s great! AFK? Nope, I decide to try something to make it happen. Follow me~
First thing first, we should know how shouldComponentUpdate()
works in React. Let’s see an example.
A simple nested component in React, initial count value is 0 and defined in Main
. Parent
and Child
components take count value from props and display. Every time Update button clicked, count increased by 1.
Left to right, screenshot #1–3 accordingly. #1 is mounting and #2–3 are updating. The difference between #2 and #3 is shouldComponentUpdate()
. I added one condition that it returns false when count > 4 in Parent
. From stack trace, Parent’s
shouldComponentUpdate()
returns false, its render()
will not be accessed any more. Naturally, any subcomponents in Parent
are no longer re-render. Updating process is interrupt.
Now I convert this demo from React to Vue.
1. Watch or computed
In order to prevent text update, first thing came into my mind is checking count. In Parent
props: ['count'],
data() {
return {
text: `Parent - ${this.count}`
};
},
watch: {
count(val, oldVal) {
if (val > 4) {
return;
}
this.text = `Parent - ${val}`;
}
}
Or
props: ['count'],
computed: {
text() {
if (this.count > 4) {
return this.prevText;
}
this.prevText = `Parent - ${this.count}`;
return this.prevText;
}
},
created() {
this.prevText = `Parent - ${this.count}`;
}
No matter watch or computed, the core concept is saving previous text every time. When count > 4, directly return previous text. Shown below
From result, it achieves the goal. But defect is obvious, it just updates using same value. Track information tells us, Parent
and Child
components still got updated. From re-render perspective, this is not shouldComponentUpdate()
, not even close.
2. V-once
Vue doc says, it renders the element and component once only. On subsequent re-renders, the element/component and all its children will be treated as static content and skipped. This can be used to optimize update performance. (link)
This description is similar to shouldComponentUpdate()
in React. It seems that there is a better way. In Main
<template v-if="count < 4">
<Parent :count="count"/>
</template>
<template v-else>
<Parent v-once :count="count"/>
</template>
When count === 4, conditional render Parent
with v-once. Destroyed old instance and create new one. Now Parent
becomes static content.
Ha! Now it is more like shouldComponentUpdate()
. In screenshot #6, only Main
got updated. Parent and Child are frozen.
Sample code, https://github.com/ocleo1/vue-should-component-update