shouldComponentUpdate() in Vue

Chris Wan
3 min readJul 9, 2019
Cover

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.

React Screenshot #1, #2 and #3 (Left to right)

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

Vue Screenshot #1, #2 and #3 (Left to right)

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.

Vue Screenshot #4, #5 and #6 (Left to right)

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

--

--