Why my button gets updated when I change a non-related data?

Here’s the code:

<div id="app">
  <p>{{result}}</p>
  <button @click="result = Math.random()">{{random()}}</button>
</div>
new Vue({
  el: '#app',
  data: {
    result: 'null',
  },
  methods: {
  	random() {
    	return Math.random().toFixed(4)
    },
  },
})

And here’s a live demo: https://jsfiddle.net/z1m7ancv/

As you can see, the button is labeled by the returned value of method random, and updates result when it gets clicked. My problem is: why clicking the button makes the label gets updated when the clicking changes nothing related to it? (Or is it related?) Is there anything I need to know about calling a method during the interpolation?

That’s how the render process works: everytime that any reactive dependency changes, the component’s whole virtual DOM is re-rendered, diffed and patched.

Why not just track related nodes and update them (since it seems possible during template compilation)? I feel that a whole-tree re-render is kind of overkill.

But the data that methods rely on might have changed, and Vue doesn’t track dependencies for methods, so they must be called again. When possible you should use a computed property instead of a method.

2 Likes

That’s in fact kind of what Vue did in version 1.*.The downside of that approach is that you have to create individual watchers for all those relationships, which results in longer initial mounting times and higher memory usage compared to Vue 2, which only needs one watcher instance per component

It was an explicit design decision for 2.0 to abandon this approach and re-render the whole component as a kind of middle ground. We experienced much better performance with this approach overall.

Of course it has its own downsides where performance can get worse, but that can usually optimized by encapsulating those areas in their own components.

1 Like

Thanks for your explanations. I understand this much better now.