Inheriting components with vue js

I am trying to build a DataComponent base that will contain the general functionality needed by many other components that deal with basic CRUD objects.
Still i

 //main.js import Vue from 'vue'; new Vue({ el:'#app', components:{ DataComponent, Quotation } }); 

 //data-component.js import Vue from 'vue'; export default Vue.extend({ data() { return { saved: false } }, methods: { //This method will be used by all inheriting components to alert //the user regarding any changes which need to be saved. alertSave(entity, fields, intFields) { var changeCount = 0; fields.forEach(function(field) { var compareWith = this[field]; //Here "this" need to refer to the child instance but it does not //how can I achieve? if ((compareWith || entity[field.camelToSnake()]) && entity[field.camelToSnake()] !== compareWith) { changeCount++; } }); intFields.forEach(function(field) { var compareWith = parseInt(this[field]); if ((compareWith || entity[field.camelToSnake()]) && entity[field.camelToSnake()] !== compareWith) { changeCount++; } }); vm.saved = changeCount <= 0; }, //sanitizeValue method works as intended as it does not have any reference to "this" sanitizeValue(value) { if (value) { return String(value).trim(); } else { return null; } }, //In getDbData method also this needs to refer to the inheriting child instance //from where this method is called - how can I achieve it? getDbData(entity) { if (entity) { this.dbTextFields.forEach(function(field) { this[field] = entity[field.camelToSnake()]; }); this.dbIntFields.forEach(function(field) { this[field] = entity[field.camelToSnake()]; }); this.dbObjFields.forEach(function(field) { this[field] = entity[field.camelToSnake()]; }); this.dbAppendedFields.forEach(function(field) { this[field] = entity[field.camelToSnake()] }); this.saved = true; } } }); 

 //quotation.js import DataComponent from './data-component'; export default DataComponent.extend({ data(){ return{ id:0, date:'', remarks:'', terms:'', quote:{}, dbTextFields:['to', 'org', 'address', 'items', 'description', 'quoted_by'], dbIntFields:['quote_ref', 'quantity', 'amount', 'discount', 'total'], dbObjFields:['inquiry', 'booking'] } }, methods:{ setDbData(){ let entity = this.quote; this.getDbData(entity); //getDbData gives error as "this" in getDbData does not refer to this // child component and so this.dbTextFields becomes undefined. } } }); 
 How to achieve method inheritance as I am trying to do? Is it possible in Vue.js? 

Edit

If I change the method signature in data-component.js as follows, passing the instance of the inheriting component ("this") as vm, it works

 //data-component.js import Vue from 'vue'; export default Vue.extend({ data() { return { saved: false } }, methods: { //This method will be used by all inheriting components to alert //the user regarding any changes which need to be saved. alertSave(entity, fields, intFields, vm) { var changeCount = 0; fields.forEach(function(field) { //var compareWith = this[field]; var compareWith = vm[field]; //Changed "this" to vm (passed as a parameter) //how can I achieve? if ((compareWith || entity[field.camelToSnake()]) && entity[field.camelToSnake()] !== compareWith) { changeCount++; } }); intFields.forEach(function(field) { //var compareWith = parseInt(this[field]); var compareWith = parseInt(vm[field]); if ((compareWith || entity[field.camelToSnake()]) && entity[field.camelToSnake()] !== compareWith) { changeCount++; } }); vm.saved = changeCount <= 0; }, //sanitizeValue method works as intended as it does not have any reference to "this" sanitizeValue(value) { if (value) { return String(value).trim(); } else { return null; } }, //In getDbData method also this needs to refer to the inheriting child instance //from where this method is called - how can I achieve it? getDbData(entity, vm) { //instance as "vm" parameter //change all this to vm if (entity) { vm.dbTextFields.forEach(function(field) { vm[field] = entity[field.camelToSnake()]; }); vm.dbIntFields.forEach(function(field) { vm[field] = entity[field.camelToSnake()]; }); vm.dbObjFields.forEach(function(field) { vm[field] = entity[field.camelToSnake()]; }); vm.dbAppendedFields.forEach(function(field) { vm[field] = entity[field.camelToSnake()] }); vm.saved = true; } } }); 

And then in the inheriting component

 //quotation.js import DataComponent from './data-component'; export default DataComponent.extend({ data(){ return{ id:0, date:'', remarks:'', terms:'', quote:{}, dbTextFields:['to', 'org', 'address', 'items', 'description', 'quoted_by'], dbIntFields:['quote_ref', 'quantity', 'amount', 'discount', 'total'], dbObjFields:['inquiry', 'booking'] } }, methods:{ setDbData(){ let entity = this.quote; this.getDbData(entity, this); //passing this (instance) as a parameter } } }); 

By passing an instance ("this") to methods like vm, it works as expected.

I am not sure if this is the best way to do this. But then this is certainly not inheritance. How to use inheritance to achieve what I'm trying to do?

+6
source share
1 answer

You should use Mixins to add general functionality to several (or all of your) components: https://vuejs.org/guide/mixins.html

This allows you to add the same functions to any or all of your components, so you can automatically add this.foobar() to your components.

If you want to add functionality to all your components without polluting the component namespace, you can use your own plugin: https://vuejs.org/guide/plugins.html

This will allow you to add the service to all of your components so that you can use it everywhere like this.$service.foobar() .

If you want to work with CRUD functionality, you must create a resource using VueResource : https://github.com/vuejs/vue-resource/blob/master/docs/resource.md

This will allow you to easily create / delete / edit resources using FoobarService.create({foo: 'bar'}) or FoobarService.delete({id: 1})

Edit: to create a plugin, it will look something like this:

 var MyPlugin = {}; MyPlugin.install = function (Vue, options) { var service = { foo: function(bar) { //do something } } Vue.prototype.$service = service; } Vue.use(MyPlugin); //this runs the install function //Then when you have any Vue instance this.$service.foo(bar); 
+7
source

All Articles