Search code examples
javascriptvue.jsvue-cli

Vue watch unexpectedly called twice


udpate #2: It is not a bug, it was my own fault. I extended the BaseComponent by a extend() method as well as putting extends: BaseComponent into the options. I thought I needed both, but extends: BaseComponent in the options seems to be enough.
So the double "extend" has apparently duplicated the watcher which lead to the strange behavior I documented in my question.

update: I found out what causes this problem: The watcher seems to be duplicated, because it's in a BaseComponent which is extended by the Component which is used in my example. so export default BaseComponent.extend({ name: 'Component', ...}) seems to duplicate the watch object instead of "merging" it - there is now one in the BaseComponent (where it is implemented initially) and one in the Component - and of course both react to prop-updates.
This seems to be a bug IMHO.


Using vue-cli with single file components.
I am setting a prop in one component via a method:

<template>
  <div>
    <other-component :my-object="myObject" />
  </div>
</template>

<script>
  export default (Vue as VueConstructor).extend({
    data() {
      return {
        myObject: null
      }
    },

    methods: {
      actionButtonClicked(action, ID) {
        console.log('actionButtonClicked');

        this.myObject = {
          action: action,
          ID: ID
        }
      }
    }
  });
</script>

then I am watching the prop in the other component with a watcher - but watch gets called twice on every execution of the method.

<script>

  export default (Vue as VueConstructor<Vue>).extend({
    /* ... */
    props: {
      myObject: {
      type: Object,
      default: null
    },

    watch: {
      'myObject.ID'(value, oldValue) {
        console.log('watcher executed');
      }
    }

    /* ... */
  });

</script>

so in the console i get the output:

actionButtonClicked
watcher executed
watcher executed

.. every time the method gets called.

I already tried all different variants of watchers - for example with deep: true + handler. but this all didn't change anything about the watcher being called twice.


Solution

  • My watcher was duplicated because I was extending my BaseComponent in two ways:

    • by the extend() method of the component itself
    • by putting extends: BaseComponent into the options of the "outer" component

    I thought you needed to use both pieces of code to extend another component, but apparently this is wrong and can lead to bad side effects.