You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue文本框每次按键触发XHR请求页面重载,setTimeout设置报错如何解决

问题描述

我有一个用于输入描述的文本框,每次按键都会触发如下日志且页面发生重载:

XHR finished loading: PATCH "http://localhost:3000/ccenter/attachments/51".

我打算给值的设置添加防抖来减少请求次数,刚接触JS还没找到合适的实现方式,尝试的写法抛出了如下错误:

[Vue warn]: Error in render: "TypeError: Setter must be a function: 3"

attachmentAccepted: {
  get: function () {
    return !this.attachment.ignoreAttachment;
  },
  set: setTimeout(function (val) {
    return this.updateAttachment([this.attachment.id, { ignoreAttachment: !val }]);
  }, 3000)
},

错误原因

计算属性的set要求赋值为函数类型,但setTimeout执行后返回的是数字类型的定时器ID,不符合setter的类型要求,因此抛出错误。

第一次修改后问题

调整set的写法后不再触发重载,但出现新错误,文本输入框的值无法正常注册:

set: function (val) { setTimeout(function(){ return this.updateAttachment([this.attachment.id, { strValue: val }]) }, 3000)  },

报错信息:

Uncaught TypeError: Cannot read properties of undefined (reading 'id')

错误原因

setTimeout内的普通函数执行时会丢失上层作用域的this指向,此时函数内的this指向全局对象(浏览器环境下为window),全局对象不存在attachment属性,因此读取id时报未定义错误。

最终解决方案

通过变量暂存上层作用域的this,在定时器回调内使用暂存的变量访问组件实例即可:

set: function (val) { 
  let self = this; 
  setTimeout(function(){ 
    /* 业务代码,所有原本用this访问的属性都替换为self访问 */
    self.updateAttachment([self.attachment.id, { strValue: val }])
  }, 3000)  
}

你也可以使用箭头函数简化写法,箭头函数的this会继承上层作用域的指向,无需额外暂存:

set: function (val) { 
  setTimeout(() => { 
    this.updateAttachment([this.attachment.id, { strValue: val }])
  }, 3000)  
}

注意:以上写法仅实现了延迟执行,没有真正的防抖效果(多次触发会生成多个定时器,等待时间结束后还是会全部执行),如果需要完整防抖功能,可以提前存储定时器ID,每次触发set时先清空上一个定时器:

set: function (val) {
  // 清空上一次的定时器
  clearTimeout(this.updateTimer)
  // 存储新的定时器ID
  this.updateTimer = setTimeout(() => {
    this.updateAttachment([this.attachment.id, { strValue: val }])
  }, 300)
}

内容的提问来源于stack exchange,提问作者user16741832

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 15:06:03