您可以将外部函数作为道具传递给Vue组件吗?

时间:2019-07-12 01:37:02

标签: javascript vue.js

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

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

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

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

  

属性或方法“ hi”未在实例上定义,但在渲染期间被引用。通过初始化属性,确保在data选项中或对于基于类的组件,此属性都是反应性的。参见: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>

1 个答案:

答案 0 :(得分:0)

您可以在组件中定义如下方法:

...
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')
  }
}