Vue.js inheritance call parent method
Solution 1
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(...);
Solution 2
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:
- 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).
- Further elaboration about the solution (whys and hows): https://github.com/vuejs/vue/issues/2977
- 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"
Solution 3
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://vuejs.org/v2/api/#extends replaces the usage of Vue.extends()
MyFantasy512
Updated on July 10, 2022Comments
-
MyFantasy512 almost 2 years
Is it possible to use method overriding in Vue.js?
var SomeClassA = Vue.extend({ methods: { someFunction: function() { // ClassA some stuff } } }); var SomeClassB = SomeClassA.extend({ methods: { someFunction: function() { // CALL SomeClassA.someFunction } } });
I want to call ClassA someFunction from ClassB someFunction. Is it even possible?
-
MyFantasy512 about 8 years1. It's pretty good solution when it comes to last resort, but it's not very extensible. 2. I've thought about using Mixins here, but necessity of changing function names is not extensible either. 3. Can u even get this working!? jsfiddle.net/9s146cdr/1 . This would be best bet, if only it was true :)
-
nils about 8 yearsI really don't recommend using #3 and I only included it for reference. The other two are much more idiomatic for vue (inheritance generally doesn't make too much sense, since componentA is not an abstract class but a parent component in the DOM with different responsibilities than componentB). It probably helps if you think less about extensibility and more about component responsibilities.
-
MyFantasy512 about 8 yearsYou can't use #3 because it's not working :) I cannot agree with since componentA is not an abstract class but a parent component in the DOM with different responsibilities than componentB because I miss-named classes, it should be
SomeAbstractComponentA
. I come to Vue from Ember, and in my opinion inheritance in components isn't anything wrong. -
nils about 8 yearsAlso, your example of using vue is not correct. You shouldn't call
new
on a component. I'll prepare an example... This is not Ember ;) -
MyFantasy512 about 8 yearsOf course this fiddle was just to prove that #3 option is not working. I am instancing components in templates.
-
MyFantasy512 about 8 yearsStepping aside component responsibilities, you cannot say that extensibility using simple concept like overriding methods, is too much abstraction for any framework.
-
nils about 8 yearsWell, option 3 only works in parent-child relationships of components. As I said, you can't do
A.extend
. If you want to extend from an independent component (not in a parent-child relationship), mixins are the only options at the moment. Actual method overriding was only introduced in ES6 classes in JavaScript, it was not native to the language before. -
nils about 8 yearsIf you really need direct extensibility, you could always write a plugin
-
MyFantasy512 about 8 yearsThanks for clarification, as I see Vue extend functionallity doesn't provide inheritance functionallity. In that case, Mixins are best solutions. Not what I expected, but thanks for giving the right direction in Vue, thanks
-
MyFantasy512 about 8 yearsSo I will just post some quick super call implementation, maybe someone would find this useful one day :) jsfiddle.net/dtq6obLp
-
akousmata over 4 yearsLate to the party and newer Vue dev, but everything I've read thus far in blogs and official documentation discourages option 1 in favor of using
$emit
in the child and handling the event in the parent. -
Hamish almost 4 yearsI don't know if something has changed since this post but I needed
FooComponent.options.methods.fooMethod.call(this);