【问题标题】:Vue.js inheritance call parent methodVue.js 继承调用父方法
【发布时间】:2016-08-14 07:59:38
【问题描述】:

是否可以在 Vue.js 中使用方法覆盖?

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

var SomeClassB = SomeClassA.extend({
  methods: {
    someFunction: function() {
      // CALL SomeClassA.someFunction
    }
  }
});

我想从 ClassB someFunction 中调用 ClassA someFunction。有没有可能?

【问题讨论】:

    标签: javascript vue.js inheritance methods method-call


    【解决方案1】:

    不,vue 不适用于直接继承模型。据我所知,你不能A.extend 一个组件。它的父子关系主要通过道具和事件来运作。

    但是有三种解决方案:

    1.传递道具(父子)

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

    在 SomeComponentA 的模板中:

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

    2。混合

    如果这是您想在其他地方使用的常用功能,则使用 mixin 可能更符合习惯:

    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.调用父道具(父子,丑)

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

    【讨论】:

    • 1.在万不得已的情况下,这是一个很好的解决方案,但它的可扩展性不是很好。 2.这里有考虑过使用Mixins,但是修改函数名的必要性也不是可扩展的。 3. 你能搞定这个吗!? jsfiddle.net/9s146cdr/1 。这将是最好的选择,如果它是真的:)
    • 我真的不推荐使用#3,我只是将它包含在参考中。其他两个对于 vue 来说更惯用(继承通常没有太大意义,因为 componentA 不是抽象类,而是 DOM 中的父组件,其职责与 componentB 不同)。如果您少考虑可扩展性而多考虑组件职责,这可能会有所帮助。
    • 你不能使用#3,因为它不起作用 :) 我不能同意 因为 componentA 不是抽象类,而是 DOM 中的父组件,其职责与 componentB 不同 因为我错过了命名类,它应该是SomeAbstractComponentA。我从 Ember 来到 Vue,在我看来,组件中的继承并没有什么问题。
    • 另外,您使用 vue 的示例不正确。您不应该在组件上调用 new。我会准备一个例子……这不是 Ember ;)
    • 当然,这个小提琴只是为了证明#3 选项不起作用。我在模板中实例化组件。
    【解决方案2】:

    如果有人对 JustWorksTM 解决方案感兴趣:

    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/


    更多信息:

    1. 此解决方案适用于由于某种原因无法使用 TypeScript 的开发人员(我认为这允许将 vue 组件定义为类,从而允许完全继承功能集)。
    2. 进一步阐述解决方案(为什么和如何):https://github.com/vuejs/vue/issues/2977
    3. 考虑到这里没有使用火箭科学,这并没有那么难看(调用匿名函数并替换了 this 指针对于任何体面的 js 开发人员来说都不是魔法)。

    如何使用Function.prototype.call()

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

    示例代码:

    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"
    

    【讨论】:

    • 我不知道这篇文章之后是否有什么变化,但我需要FooComponent.options.methods.fooMethod.call(this);
    【解决方案3】:

    如果有人在这里寻求解决方案,这是我的,并且工作正常:

    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
            },
        },
    };
    

    使用 https://vuejs.org/v2/api/#extends 中的 juste extends 替换 Vue.extends() 的用法

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-02
      • 2013-12-25
      • 2017-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-15
      • 2012-01-06
      相关资源
      最近更新 更多