Vue.js inheritance call parent method

In case someone asks for a solution here is mine and works fine :

var SomeClassA = {
    methods: {
        someFunction: function () {
            this.defaultSomeFunction();
        },
        // defaultSomeFunction acts like parent.someFunction() so call it in inheritance
        defaultSomeFunction: function () {
            // ClassA some stuff
        },
    },
};

var SomeClassB = {
    extends: SomeClassA,
    methods: {
        someFunction: function () {
            // Replace the wanted SomeClassA::someFunction()
            this.defaultSomeFunction();
            // Add custom code here
        },
    },
};

using juste extends from https://v2.vuejs.org/v2/api/#extends replaces the usage of Vue.extends()


In case someone's interested in a JustWorksTM solution:

var FooComponent = {
  template: '<button @click="fooMethod()" v-text="buttonLabel"></button>',

  data: function () {
   return {
     foo: 1,
     bar: 'lorem',
     buttonLabel: 'Click me',
   }
  },

  methods: {
    fooMethod: function () {
      alert('called from FooComponent');
    },
    
    barMethod: function () {
      alert('called from FooComponent');
    },
  }
}

var FooComponentSpecialised = {
  extends: FooComponent,

  data: function () {
   return {
     buttonLabel: 'Specialised click me',
     zar: 'ipsum',
   }
  },

  methods: {
    fooMethod: function () {
      FooComponent.methods.fooMethod.call(this);
    
      alert('called from FooComponentSpecialised');
    },
  }
}

jsfiddle: https://jsfiddle.net/7b3tx0aw/2/


More info:

  1. This solution is for devs that can't use TypeScript for some reason (which I think allows defining vue components as classes, which in turn allows full inheritance feature-set).
  2. Further elaboration about the solution (whys and hows): https://github.com/vuejs/vue/issues/2977
  3. This ain't that ugly, considering that no rocket science is used here (calling anonymous functions with the this pointer replaced should be no magic for any decent js dev).

How to use Function.prototype.call()

Reference https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call

Sample code:

function Product(name, price) {
  this.name = name;
  this.price = price;
}

function Food(name, price) {
  Product.call(this, name, price);
  this.category = 'food';
}

console.log(new Food('cheese', 5).name);
// expected output: "cheese"

No, vue doesn't work with a direct inheritance model. You can't A.extend an component, as far as I know. It's parent-child relationships work mainly through props and events.

There are however three solutions:

1. Passing props (parent-child)

var SomeComponentA = Vue.extend({
    methods: {
        someFunction: function () {
            // ClassA some stuff
        }
    }
});

var SomeComponentB = Vue.extend({
   props: [ 'someFunctionParent' ],
   methods: {
       someFunction: function () {
           // Do your stuff
           this.someFunctionParent();
       }
   }
});

and in the template of SomeComponentA:

<some-component-b someFunctionParent="someFunction"></some-component-b>

2. Mixins

If this is common functionality that you want to use in other places, using a mixin might be more idiomatic:

var mixin = {
    methods: {
        someFunction: function() {
            // ...
        }
    }
};

var SomeComponentA = Vue.extend({
    mixins: [ mixin ],
    methods: {
    }
});

var SomeComponentB = Vue.extend({
   methods: {
       someFunctionExtended: function () {
           // Do your stuff
           this.someFunction();
       }
   }
});

3. Calling parent props (parent-child, ugly)

// In someComponentB's 'someFunction':
this.$parent.$options.methods.someFunction(...);