vue3中动态调用函数?

在vue2中可以这样做:

 created(){
    let eventName = 'toBuy'
     this[eventName]()
 }
 methods:{
    toBuy(){...}
 }
在vue3+ts中这样做会报错
handleSome('toBuy')
const handleSome(funcName:string) = ()=>{
 //写法一:会被ts当作字符串数组,不能调用
    [funcName]()  
 //写法二:不能执行,报ts错误,Type 'String' has no call signature    
    const tempObj={[funcName]:funcName}
    tempObj[funcName]()                
}
const toBuy = () => {
    ...
}

在vue3中要实现这种动态调用函数应该怎么做。。。
目的是要封装el-table的操作列
image.png

根据香芋的思路,还是不执行,看起来逻辑是没错,但是onSubmit的方法没有被调用。。。
image.png
image.png

可能我描述能力太弱了,如果按照二三楼的回答,其实我上图的写法就能实现了,问题是ts语法这块有限制,虽然我的tempObj[fun]就是onSubmit,按照js,这块完全可以执行,调用onSubmit(),但是ts会认为(tempObj[fun])的值为string,不能作为方法调用

阅读 5.9k
5 个回答
2023-03-09 16:59:33 补充

tempObj = { [fun]: fun } 这里,因为 fun: string,所以它是一个 { [key]: string } 类型没毛病,tempObj["..."] 得到的确实是一个字符串,不能直接调用。

用 TS 写的话,可以主动声明 tempObj 的属性值类型

tempObj: {[key: string]: (...args: any[]) => any } = {
   ...
}

当然这里用了通用的函数类型,兼容各种函数。根据应用场景,类型能准确一些更好。


之前的回答

把定义的函数封装到一个对象中就可以

<script setup>
import { ref } from 'vue'

const msg = ref('Hello World!');
const result = ref("");
  
function test1() {
  return "hello test1";
}
  
function test2() {
  return "hello test2";
}
  
const actions = { test1, test2 };

function handle(name) {
  result.value = (actions[name] ?? (() => "not found action"))();
}
</script>

<template>
  <h1 @click="handle(msg)">{{ msg }}</h1>
  <input v-model="msg">
  <div>{{ result }}</div>
</template>

示例:Vue3 Playground 去看看


const handleSome = (funcName)=>{
    const actions = { toBuy }
    actions[funcName]()   //不能执行
}
const toBuy = () => {
    ...
}
handleSome('toBuy')
<script setup lang="ts">
import { ref } from 'vue';

const count = ref(0);
const map = {
    toBuy
}

function handler(func) {
  map[func]();
}

function toBuy() {
  console.log(456);
}
</script>

<template>
  <button @click="handler('toBuy')">{{ count }}</button>
</template>
const toBuy = () => alert(0);
const handleSome = funcName => ({toBuy})[funcName]();

不过这样用 RPC 代替回调订阅的写法多少有点奇怪,通常应该是父组件监听子组件emit然后调用对应的handler

<child @toBuy="toBuy"></child>

结合边城和香芋的回答最后使用如下:
使用页面:image.pngimage.png
table的封装页面:
image.png

推荐问题
logo
Microsoft
子站问答
访问
宣传栏