Наследование компонентов с помощью vue js

Я пытаюсь построить базу DataComponent который будет содержать общую функциональность, необходимую для многих других компонентов, которые имеют дело с базовыми сущностями CRUD.
До сих пор у меня

//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?  

редактировать

если я изменю сигнатуру метода в data-component.js как ниже, передавая экземпляр наследования компонента ("это") как ВМ , он работает

//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;

              }
            }
        });

а затем в наследующем компоненте

//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
      
      
    }
  }
  
});

передавая экземпляр ("это") методам как vm, он работает так, как ожидалось.

Я не уверен, что это лучший способ сделать это. Но тогда это, конечно, не наследство.
Как использовать наследование для достижения того, что я пытаюсь сделать?

1 ответов


вы должны использовать Mixins для добавления общих функций к нескольким (или всем) компонентам:https://vuejs.org/guide/mixins.html

это позволит вам добавить те же функции к любому или всем вашим компонентам, поэтому вы можете автоматически добавить this.foobar() для ваших компонентов.

если вы хотите добавить функциональность ко всем своим компонентам, не загрязняя пространство имен компонентов, вы можете использовать пользовательский плагин: https://vuejs.org/guide/plugins.html

это позволит вам добавить сервис ко всем вашим компонентам, чтобы вы могли использовать его везде, как this.$service.foobar().

если вы хотите работать с функциональностью CRUD, вы должны создать ресурс, используя VueResource: https://github.com/vuejs/vue-resource/blob/master/docs/resource.md

это позволит вам легко создавать/удалять/редактировать ресурсы с помощью FoobarService.create({foo: 'bar'}) или FoobarService.delete({id: 1})

Edit: для создания плагин, он будет выглядеть примерно так:

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);