在Vue组件中使用匿名函数作为事件处理程序

时间:2019-12-18 11:03:56

标签: vue.js vuejs2

我一直在环顾四周,发现最常见的解决方案是使用应用程序/组件的实例设置一个变量,然后使用该变量来更改dataExample 1Example 2)。

我的问题是我不能使用箭头功能(只允许使用ES5兼容的JS,不能使用我的电话),并且我的功能没有“先前”部分来设置应用程序实例。

var theApp = new Vue({
    el: '#the-app',
    data: {
        selectedView: 1,
        myDynamicButtonsArray: [
            {
                text: 'Change view!!'
                onClick: function () {
                    // here this.selectedView should be changed
                    this.selectedView = 2;
                }
            },
            {
                text: 'My other button'
                onClick: function () {
                    // Here something completely unrelated should happen
                }
            }
        ]
    }
});

I遍历myDynamicButtonsArray并加载一个myButton组件,该组件在单击时执行onClick

<my-button v-for="button in myDynamicButtonsArray" v-bind="button"></my-button>

问题在于,当我执行this.selectedView = 2;时,this并不是在引用应用实例,而是在执行该实例的函数实例有意义。

我尝试过这样设置值:

theApp._data.selectedView = 2;

但是我不确定这是否是正确的方法。

我之所以不使用$emit的原因是因为有许多不同的功能要执行,并发出一个button-clicked然后用一个巨大的开关执行一个通用功能,所以它会做一件事或其他取决于所按按钮的方法似乎都不可行:

// MyButton component template
<button @onClick="this.$emit('button-clicked', id)">
    {{ text }}
</button>

// App html
<my-button 
    v-for="button in myDynamicButtonsArray" 
    v-bind="button"
    @button-clicked="buttonClicked"
>
</my-button>

// App object
var theApp = new Vue({
    el: '#the-app',
    data: {
        selectedView: 1,
        myDynamicButtonsArray: [
            {
                text: 'Change view!!',
                id: 1
            },
            {
                text: 'My other button',
                id: 2
            }
        ]
    },
    methods: {
        buttonClicked: function(id) {
            switch(id) {
                case 1:
                    this.selectedView = 2; 
                    // I am not even sure if I can use 'this' the way I want here;
                    break;
                case 2:
                    // And so on for all my buttons
            }
        }
    }
});

每个按钮发出不同的事件似乎也不可行:

// MyButton component template
<button @onClick="this.$emit(customEventString)">
    {{ text }}
</button>

// App html
<my-button 
    v-for="button in myDynamicButtonsArray" 
    v-bind="button"
    @custom-event-1="customEvent1"
    @custom-event-2="customEvent2"
>
</my-button>

// App object
var theApp = new Vue({
    el: '#the-app',
    data: {
        selectedView: 1,
        myDynamicButtonsArray: [
            {
                text: 'Change view!!',
                customEventString: 'custom-event-1'
            },
            {
                text: 'My other button',
                customEventString: 'custom-event-2'
            }
        ]
    },
    methods: {
        customEvent1: function() {
            this.selectedView = 2; 
            // I am not even sure if I can use 'this' the way I want here;
        },
        customEvent2: function() {
            // Do other things
        }
    }
});

我的问题是,这是正确的方法:

  • 使用myApp._data
  • 内部有一个事件和一个switch
  • 还有其他

2 个答案:

答案 0 :(得分:1)

您可以使用bind()来更改this对任何功能的含义

<button
      v-for="button in myDynamicButtonsArray"
      @click="bindToMe(button.onClick)()"
      :key="button.text"
    >{{ button.text }}</button>
methods: {
    bindToMe(handler) {
      return handler.bind(this);
    }
  }

仅需注意@click内部的语法-我们不是直接传递处理程序,而是调用一个返回原始处理程序但将this绑定到当前Vue实例的函数。...

Demo

答案 1 :(得分:1)

首先,您需要从data属性中返回一个函数,然后将this关键字绑定到该函数

示例:

const MyButton = Vue.component('my-button', {
  template: '<button v-text="text" @click="onClick"></button>',
  props: ['text', 'onClick']
});

new Vue({
  el: '#the-app',
    
  components: { MyButton },
  
  data: function() {
    return {
      selectedView: 1,
      buttons: [
        {
          text: 'Change view!!',
          onClick: function () {
            console.log('btn 1 clicked')
            // here this.selectedView should be changed
            this.selectedView = 2;
          }.bind(this)
        },
        {
          text: 'My other button',
          onClick: function () {
            console.log('btn 2 clicked')
            // Here something completely unrelated should happen
          }
        }
      ]
    }
  }
});
<div id="the-app">
  {{ selectedView }}
  <my-button v-for="(button, index) in buttons" :key="index" v-bind="button" />
</div>


<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>