VueJS中v-on绑定的事件函数更新后未生效问题求助
问题原因
你遇到的问题是因为Vue默认不会追踪事件监听函数的引用变化。当你在模板里写@main-action="mainAction"时,Vue会在初始渲染时把这个事件绑定到当时的mainAction函数引用上,后续即使this.mainAction被重新赋值为新的箭头函数,Vue也不会自动更新这个事件绑定——因为事件监听的绑定逻辑不会随变量引用变化而触发更新,而props之所以能正常更新是因为Vue会深度追踪props的响应式变化。
解决方案
这里提供两种适合Vue类组件的可行方案:
方案1:用内联函数包裹事件绑定
修改Foo组件的模板,把事件绑定改成内联箭头函数的形式,这样每次父组件渲染时都会使用最新的mainAction引用:
@Options({ template: ` <modal @main-action="(event) => mainAction(event)" > <div v-html="body"></div> </modal> `, components: { Modal }, }) export class Foo extends Vue { // ... 其他代码 this.mainAction = () => { console.log("within mainAction"); console.log(options?.debuggingId) } // ... 其他代码 }
注意:内联函数会在每次父组件渲染时创建新的函数实例,但对于模态框这种低频率触发的组件,性能影响可以忽略。
方案2:将事件处理函数作为props传递给Modal组件
这种方式利用Vue的props响应式追踪机制,确保函数更新时Modal组件能实时感知:
第一步:修改Modal组件,新增props接收处理函数
@Options({ props: { mainActionFn: { type: Function, required: true } } }) export default class Modal extends Vue { // ... 其他代码 public mainActionClick(event: MouseEvent): void { // 直接调用props传入的函数,替代$emit this.mainActionFn(event) } }
第二步:修改Foo组件的模板,传递props替代事件绑定
@Options({ template: ` <modal :main-action-fn="mainAction" > <div v-html="body"></div> </modal> `, components: { Modal }, }) export class Foo extends Vue { // ... 其他代码 this.mainAction = () => { console.log("within mainAction"); console.log(options?.debuggingId) } // ... 其他代码 }
补充说明
如果你坚持要用$emit的方式,还可以通过监听mainAction的变化,手动调用Modal组件的$off和$on来更新事件绑定,但这种方式需要用到$refs,代码复杂度更高,不如上面两种方案简洁。
内容的提问来源于stack exchange,提问作者JSFernandes
相关产品推荐
相关产品推荐

