【问题标题】:Vue.js 2: converting a string in a function call at an event handlerVue.js 2:在事件处理程序的函数调用中转换字符串
【发布时间】:2021-11-17 16:34:03
【问题描述】:

在 Vue.js 2 中,我想将字符串转换为函数调用,以便可以将其设置为事件处理程序。 我相信这将非常实用,特别是在基于对象列表动态创建大量元素(例如按钮)时。

new Vue({
  el: "#app",
  data: {
    myArray: [
      { value: 1, fn: "firstMethod" },
      { value: 2, fn: "secondMethod" },
    ],
  },
  methods: {
    firstMethod() {
      console.log("'firstMethod' was executed.");
    },
    secondMethod() {
      console.log("'secondMethod' was executed.");
    },
  },
});
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <template v-for="elem in myArray">
        <button @click="elem.fn">  <!-- Here is where I am stucked. -->
          <!-- <button> -->
          {{elem.value}}
        </button>
      </template>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    <script src="script.js"></script>
  </body>
</html>

我第一次尝试这样做是将myArray 中的fn 属性设置为指向具有this 的相应函数的指针(例如fn: this.firstMethod)。问题是,我相信,在定义的时候,这些功能仍然是未知的,正如我得到的那样:[Vue warn]: Invalid handler for event "click": got undefined

我正在努力实现的目标是否可能?我忽略了这个策略有什么缺点吗?

【问题讨论】:

  • 我不认为你想要实现的目标是可能的,在我自己看来,这看起来并不动态
  • 为什么不只使用一个函数,该函数会根据传递给函数的参数产生不同的输出,并将这些唯一参数赋予myArray中的每个对象
  • 你不应该写没有引号的函数fn: "firstMethod"吗?否则它是一个字符串,对吗?所以fn: firstMethod 应该引用方法本身。不是this.,因为这在模板中不是必需的。我会试试的。
  • @rubebop 是的,这个函数会变得很庞大......你能给我一个你会使用这种方法的场景......让我看看我是否可以提供更好的方法
  • @rubebop 哦,没错,当您在创建data 期间引用该函数时,该方法尚不存在。你可以坚持你找到的解决方案。我发现的另一种方法是覆盖create() 并在那里分配要调用的函数。但这可能还不够自我解释。

标签: javascript html vue.js vuejs2


【解决方案1】:

尝试创建一种适用于所有按钮的方法

new Vue({
  el: "#app",
  data: {
    myArray: [
      { value: 1, fn: "firstMethod" },
      { value: 2, fn: "secondMethod" },
    ],
  },
  methods: {
    basicMethod(name) {
      console.log(`'${name}' was executed.`);
      if(name === 'firstMethod') {
        //some logic, and so on for other methods if u need
      }
    },
  },
});
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <template v-for="elem in myArray">
        <button @click="basicMethod(elem.fn)">  <!-- Here is where I am stucked. -->
          <!-- <button> -->
          {{elem.value}}
        </button>
      </template>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    <script src="script.js"></script>
  </body>
</html>

【讨论】:

  • 是的,这是@onifadeboluwatife 在之前的cmets 中建议的解决方案。它肯定工作正常。唯一的缺点是,当有很多元素时,函数会变得笨重。我也从答案中猜测,我原来的方法是不可能的。
  • @rubebop 例如,你可以将每个函数的逻辑移动到一个单独的文件中
【解决方案2】:

您可以使用函数名称提供的泛型方法调用this[ fn ]();

但出于安全原因,您可能希望这些自定义方法位于对象中,而不仅仅是在主 this 上,因此无法调用其他方法。

另外,你想在调用它之前检查方法是否存在。

看起来像这样:

new Vue({
  el: "#app",
  data: {
    myArray: [
      { value: 1, fn: "firstMethod" },
      { value: 2, fn: "secondMethod" },
      { value: 3, fn: "nonExistingMethod" }, // Won't throw an error
      { value: 4, fn: "someImportantSecureMethod" }, // Won't be called
    ],
    customMethods: {
      firstMethod: function() {
        console.log("'firstMethod' was executed.");
      },
      secondMethod: function() {
        console.log("'secondMethod' was executed.");
      },
    },
  },
  methods: {
    callCustomMethod(fn) {
      // Make sure it exists
      if (typeof this.customMethods[fn] === "function") {
        // Only methods inside the customMethods object are available
        this.customMethods[fn]();
      }
    },
    someImportantSecureMethod() {
      console.log('The method may not be exposed to dynamic calling!');
    },
  },
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
    <template v-for="elem in myArray">
        <button @click="callCustomMethod(elem.fn)">
            <!-- <button> -->
            {{elem.value}}
        </button>
    </template>
</div>

附注: 您也可以考虑为此使用自定义事件 (see docs)。使用$emit('custom-event-name') 作为v-on:click 处理程序,并将您的自定义方法作为事件侦听器。 (当您以后可能想要将项目制作成单独的组件时,这很容易。)

【讨论】:

  • 谢谢!这是有道理的(我也想过这个解决方案,但我错过了this[ fn ]() thing)。我也很欣赏有关安全方面的意见,最后是发出自定义事件的想法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多