Vue.js 2如何将字符串转换为函数调用作为事件处理器
问题根源
你在data初始化阶段直接引用this.firstMethod报错,是因为Vue实例的初始化顺序是 initProps → initData → initMethods,定义data的时候methods还没挂载到实例上,自然拿不到对应函数,返回undefined就会触发事件处理器无效的报错。
可行实现方案
你的需求完全可以实现,这里提供两种常用的实现方式:
方案1:模板内直接通过方法名调用
直接在点击事件里通过实例下标取对应方法执行,不需要额外新增逻辑:
<button @click="this[elem.fn]()"> {{elem.value}} </button>
如果需要传递参数,比如要把当前遍历的elem作为参数传给方法,直接加在括号里即可:
<button @click="this[elem.fn](elem)"> {{elem.value}} </button>
方案2:封装统一调用方法(更推荐)
在methods里新增一个通用的方法调用代理,后续要加参数校验、埋点之类的逻辑都可以在这里统一处理,可维护性更高:
首先修改JS代码:
new Vue({ el: "#app", data: { myArray: [ { value: 1, fn: "firstMethod" }, { value: 2, fn: "secondMethod" }, ], }, methods: { // 新增通用调用方法 invoke(fnName, ...args) { // 可以加层判断,避免方法不存在时报错 if (typeof this[fnName] === 'function') { this[fnName](...args) } }, firstMethod() { console.log("'firstMethod' was executed."); }, secondMethod() { console.log("'secondMethod' was executed."); }, }, });
然后修改模板里的点击事件:
<button @click="invoke(elem.fn, elem)"> {{elem.value}} </button>
该方案的注意事项与弊端
- 没有编译期校验:方法名是字符串形式,模板编译阶段不会校验方法是否存在,只有运行时点击才会发现错误,写错方法名的排查成本更高
- 维护成本略高:后续如果方法改名,需要同步修改数组里的字符串值,否则会调用失败
- 不要把函数直接存在data里:Vue会给data所有属性做响应式劫持,函数不需要响应式,存入data只会增加不必要的性能开销,数组量越大损耗越明显
- 方法名如果是用户可控的,会有安全风险:如果myArray的数据来自后端接口,恶意用户传入危险方法名可能导致安全问题,这种场景要加方法名白名单校验。
内容的提问来源于stack exchange,提问作者rubebop
相关产品推荐
相关产品推荐

