Use current vue component's method as default prop value

瘦欲@ 提交于 2020-05-29 05:37:08

问题


I am going to pass function as property to Vue component. Let it be function has to be invoked by @click. But for some reasons I want to keep default behaviour for the component. The default behaviour is not so easy as I want and I'm going to use method as default function. Because the default behaviour requires data from component's state (props, data, other methods, whatever).

Is there a way to do?

I've attached the example. Expected behaviour:

Button works fine should produce alert You are welcome!
Button nope should produce alert You are welcome as well! but does nothing.

Vue.component('welcome-component', {
  template: '#welcome-component',
  props: {
    name: {
      type: String,
      required: true,
    },
    action: {
      type: Function,
      required: false,
      default: () => { this.innerMethod() },
    },
  },
  methods: {
    innerMethod() {
      alert("You are welcome as well!");
    }
  }
});


var app = new Vue({
  el: "#app",
  methods: {
    externalMethod() {
      alert("You are welcome!");
    }
  }
});
#app {
  margin: 20px;
}

.holder > button {
  margin: 10px;
  padding: 5px;
  font-size: 1.1em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <welcome-component name="works fine" :action="externalMethod"></welcome-component>
  <welcome-component name="nope"></welcome-component>
</div>


<script id='welcome-component' type='x-template'>
  <div class="holder">
    <button @click="action">{{ name }}</button>
  </div>
</script>

回答1:


This works but it's a total bag of spanners:

action: {
  required: false,
  default () { 
    return () => this.innerMethod();
  },
},

I've had to remove the type: Function. Usually when default is a function it will be invoked to return the appropriate default value. However, if the prop has type: Function it'll just treat the function as the default. In this case that's problematic because we lose the this binding.

The internal arrow function is required to get around the problem that the methods aren't available when the default function is called.

If possible I would suggest giving up on using a default and instead just apply the 'default' when it needs to be invoked. So rather than calling action directly in the click handler, instead call a method called invokeAction that looks something like this:

invokeAction () {
  if (this.action) {
    this.action();
  } else {
    this.innerMethod();
  }
}



回答2:


From vue docs:

"Note that props are validated before a component instance is created, so instance properties (e.g. data, computed, etc) will not be available inside default or validator functions." (https://vuejs.org/v2/guide/components-props.html)

Referencing the innerMethod is therefore one of the cases where the components function is not yet available.

Idea: If it is crucial for you to have this kind of functionality you could check within a later lifecycle hook (like created, mounted etc.) whether the type of action is function. If it's not a function (meaning not passed via prop), assign the innerMethod manually.



来源:https://stackoverflow.com/questions/57313153/use-current-vue-components-method-as-default-prop-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!