【问题标题】:Can you pass an external function to a Vue component as a prop?您可以将外部函数作为道具传递给 Vue 组件吗?
【发布时间】:2023-04-04 04:54:02
【问题描述】:

我有一个主要用 PHP 构建的遗留代码库。我正在研究如何将代码的常用部分转换为可重用的 Vue 组件,可以根据需要插入。

在一种情况下,我在 html 中有一个 onclick 事件,它需要单独传递给子组件。 onclick="func()"

我希望能够将该函数从标记传递给组件,而不是将这个一次性使用函数定义为组件或其父级的属性方法。

我在 Vue 文档或其他地方找不到有关如何执行此操作的任何内容。我所做的每一次尝试都会出错:

属性或方法“hi”未在实例上定义,但在渲染期间被引用。通过初始化该属性,确保此属性是反应性的,无论是在数据选项中,还是对于基于类的组件。见:https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties

有没有办法将全局范围内的外部定义函数传递给 Vue 实例?

Vue 选项卡:

Vue.config.devtools = true;


Vue.component('tabs', {
  template: `
    <div class="qv-tabs">
      <div class="tab">
        <ul>
          <li v-for="tab in tabs"
              :class="{'is-active' : tab.isActive}"
              @click="tab.callHandler"
          > 
            <a :href="tab.href" @click="selectTab(tab)">{{tab.name}}</a>
          </li>
        </ul>
      </div>
      <div class="tab-content">
        <slot></slot>
      </div>
    </div>
  `,
  data(){
    return{
      tabs: []
    };
  },
  created(){
    this.tabs = this.$children;
  },
  methods:{
    selectTab(selectedTab){
      this.tabs.forEach(tab => {
        tab.isActive = (tab.name == selectedTab.name);
      });
    },
    otherHi() {
      alert('other hi');
    }
  }
});

Vue.component('tab', {
  template: `
    <div v-show="isActive">
      <slot></slot>
    </div>
  `,
  props: {
    name: {required: true},
    selected: {default: false},
    callHandler: Function,
    clickHandler: {
      type: Function,
      default: function() { console.log('default click handler') }
    }
  },
  data(){
    return{
      isActive: false
    }
  },
  methods: {
    callHandler() {
      console.log('call handler called');
      this.clickHandler();
    }
  },
  computed:{
    href(){
      return '#' + this.name.toLowerCase().replace(/ /g, '-');
    }
  },
  mounted(){
    this.isActive = this.selected;
  }
});

new Vue({
  el: '.app',
  methods: {
    vueHi() { alert('hi from vue'); }
  }
});

function hi() {
  alert('hi!');
}

标记:

<div class="app">
    <tabs>
      <tab name="Tab 1" :selected="true" v-bind:call-handler="hi">
        <p>Tab content</p>
      </tab>
      <tab name="Tab 2">
        <p>Different content for Tab 2</p>
      </tab>
    </tabs>
  </div>

【问题讨论】:

  • 我从未见过需要功能性道具的好例子。你可以使用一个事件来代替,即你的组件发出一个事件并且父级处理它吗?
  • 这似乎是文档的主要建议,它使问题变得更糟。现在,我不再拥有可以处理自己的单次使用单击事件的组件,而是让其父组件的每个实例都具有组件本身从未使用过的功能,并且在子元素使用的整个代码库中只有一次。这似乎仍然是构建它的错误方法。从根本上说,我不需要传递函数式 prop,我需要允许组件在不使用方法对象或将其用作代理的情况下引用外部定义的函数。

标签: javascript vue.js


【解决方案1】:

你可以在你的组件中这样定义你的方法:

...
methods: {
   hi
}
...

但是您必须在需要此功能的每个组件中定义它。也许你可以使用一个 mixin 来定义你想要从你的组件访问的方法,并在这些组件中使用这个 mixin? https://vuejs.org/v2/guide/mixins.html

另一个解决方案(取决于您尝试实现的目标)是将您的方法添加到 Vue 原型中,如下所述: https://vuejs.org/v2/cookbook/adding-instance-properties.html

Vue.prototype.$reverseText = function(string) {
  return string.split('')
    .reverse()
    .join('')
}

通过在 Vue 原型中定义此方法,您可以在所有组件模板中使用这样的 reverseText 方法:

...
<div> {{ $reverseText('hello') }} </div>
...

或者从你的脚本中使用this

methods: {
  sayReverseHello() {
    this.$reverseText('hello')
  }
}

【讨论】:

  • 感谢您的回复。由于您提到的原因,我认为这没有帮助 - 我试图避免在每个组件上定义一次性事件函数。按照我的设想,组件应该只定义每个实例将使用的方法和属性,但应该能够接受外部函数以用于特定实例。
  • 那么,涉及在原型中添加您需要的方法的解决方案是否最适合您的需求?不幸的是,没有其他方法可以直接在模板中使用外部 javascript 函数而不像上面提到的那样包装它。
猜你喜欢
  • 2019-07-03
  • 2020-01-08
  • 1970-01-01
  • 2019-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-24
相关资源
最近更新 更多