vue2中使用节流防抖函数时,使用的vue状态始终是初始化的数据

背景

vue2。运用debounce时,遇到的问题;代码如下

js 复制代码
handleSearchOrigin(type = 'load') { //todo 刷新表格数据
      console.log('%c 🛣️ 张浩雨: extends -> handleSearchOrigin -> this.queryFormCurrent ', 'font-size:16px;background-color:#73b247;color:white;', {...this.queryFormCurrent})
    this.annexConfig.searchApi && this.annexConfig.searchApi.request({
      ...this.queryFormCurrent
    }).then((res) => {
      if (res.status && res.data) {
        const list = res.data;
        this.list = list
      }
    })
  }
  handleSearch = debounce((type = 'load') => { //todo 刷新表格数据
    console.log('%c 💿 张浩雨: extends -> handleSearch -> this.queryFormCurrent ', 'font-size:16px;background-color:#9f2689;color:white;', {...this.queryFormCurrent})
    //* 为什么这里 this.queryFormCurrent 拿到的值是 {}
    this.handleSearchOrigin(type)
  }, 300)

✅ 直接调用 this.handleSearchOrigin() → queryFormCurrent 有值

❌ 调用防抖的 this.handleSearch() → queryFormCurrent 永远是空对象 {}

问题根源非常明确,而且这个代码写法 handleSearch = debounce(()=>{...},300) 是Vue2 + TS 里触发这个 BUG 的「标准答案写法」

原因分析

✅ 致命问题:Vue2 的 methods 函数,不能用「箭头函数 + 赋值式」定义防抖方法

js 复制代码
// ❌ 错误写法(Vue2 绝对禁止!!!)
handleSearch = debounce((type = 'load') => { 
  this.handleSearchOrigin(type)
}, 300)

✔ 为什么这个写法会导致 this.queryFormCurrent 为空?

  • Vue2 的组件实例特性:Vue2 的data里声明的变量(queryFormCurrent)、methods里的方法,都是挂载到

    Vue 组件实例(this) 上的,组件内的函数能拿到this.xxx,前提是这个函数的this指向 Vue 实例。

  • 箭头函数的特性:箭头函数 ()=>{} 没有自己的this,它的this是「定义时」绑定的父级作用域的 this,而不是「执行时」的 Vue 实例。

  • 赋值式定义的坑:handleSearch = debounce(...) 这种赋值写法,是把函数挂载到了 ** 组件的「实例属性」** 上,而不是Vue的methods里,Vue 无法对这个函数做「this绑定的劫持处理」。

✔ 你的代码执行链路的真实情况(一步步解析为什么为空)

js 复制代码
// 1. 你调用防抖方法
this.handleSearch() 
// 2. 防抖内部执行箭头函数 ()=>{ this.handleSearchOrigin(type) }
// 3. 箭头函数的this → 指向「定义时的父级作用域」(不是Vue实例)
// 4. 箭头函数里的 this.queryFormCurrent → 父级作用域没有这个变量 → 空对象 {}
// 5. 执行 handleSearchOrigin 时,内部的 this 也被污染 → 同样拿到空值

解决方案

✅ 方案一:【最优推荐 ✨ 零入侵、改动最小、100% 根治】核心修复(只改 1 行代码)

✔ 核心修复逻辑

保留你所有的代码结构、保留防抖、保留handleSearchOrigin、保留所有业务逻辑,只改「防抖方法的定义方式」,把 「箭头函数」改成「普通 function 函数」 即可!

原理:普通function函数的this是「执行时绑定」,防抖执行时,this会正确指向Vue 组件实例,就能拿到this.queryFormCurrent的真实值。

【只改这 1 行,其余完全不变】

js 复制代码
// ========== 只改这里 ↓↓↓ 箭头函数 → 普通function函数 ==========
handleSearch = debounce(function(type = 'load') { 
  console.log('%c 💿 张浩雨: extends -> handleSearch -> this.queryFormCurrent ', 'font-size:16px;background-color:#9f2689;color:white;', {...this.queryFormCurrent})
  this.handleSearchOrigin(type)
}, 300)
// ========== 只改这里 ↑↑↑ ==========

// 你的其他代码 完全不变!!!
handleSearchOrigin(type = 'load') { 
    if (this.listType === 'table') { 
      const baseSearchTableRef: any = this.$refs.baseSearchTable;
      baseSearchTableRef?.handleSearch('force'); // ✅ 顺带修复拼写错误 handel → handle
      return
    }
    console.log('%c 🛣️ 张浩雨: extends -> handleSearchOrigin -> this.queryFormCurrent ', 'font-size:16px;background-color:#73b247;color:white;', {...this.queryFormCurrent})
    this.annexConfig.searchApi && this.annexConfig.searchApi.request({
      ...this.queryFormCurrent
    }).then((res) => {
      if (res.status && res.data) {
        let list = res.data;
        if (typeof this.dataTransform === 'function') {
          list = this.dataTransform(list) // ✅ 顺带修复:赋值转换后的数据
        }
        this.list = list
        this.handleEventHandler({
          event: type,
          data: this.list,
          extraParams: {
            dataSource: this.list
          }
        })
      }
    })
  }

✔ 为什么这个修复方案是最优的?

✅ 零入侵:业务逻辑一行不改,只改 1 个函数定义,成本最低;

✅ 根治问题:普通 function 的this执行时绑定 Vue 实例,queryFormCurrent必能拿到值;

✅ 保留防抖:原有防抖逻辑完全不变,不影响手动搜索的防抖性能优化;

✅ 顺带修复了 2 个隐藏 BUG,一举三得;

✅ 方案二:【兜底方案 ✨ 绝对生效、Vue2 官方推荐写法】防抖写在 methods 里(无任何 this 问题)

如果方案一你想再保险一点,这个方案是 Vue2 官方推荐的「防抖方法定义方式」,也是绝对不会有 this 指向问题的写法,属于「从根源上规避坑」,适合对代码严谨度要求高的生产环境。

✔ 核心改造逻辑

  1. 把防抖函数的定义 + 赋值,全部放到 Vue 的created钩子中;
  2. 防抖内部必须用普通 function,保证this指向正确;
  3. 所有调用方式不变,业务逻辑不变;

✔ 完整改造后代码

js 复制代码
export default {
  data() {
    return {
      listType: 'table',
      queryFormCurrent: {}, // 你的查询参数
      annexConfig: {},
      list: []
    }
  },
  created() {
    // ✅ 步骤1:在created里初始化防抖方法,赋值给methods
    this.handleSearch = debounce(function(type = 'load') {
      console.log('%c 💿 张浩雨: extends -> handleSearch -> this.queryFormCurrent ', 'font-size:16px;background-color:#9f2689;color:white;', {...this.queryFormCurrent})
      this.handleSearchOrigin(type)
    }, 300)
  },
  methods: {
    // ✅ 步骤2:原逻辑不变,修复2个小BUG
    handleSearchOrigin(type = 'load') { 
      if (this.listType === 'table') { 
        const baseSearchTableRef: any = this.$refs.baseSearchTable;
        baseSearchTableRef?.handleSearch('force'); // ✔ 修复拼写错误
        return
      }
      console.log('%c 🛣️ 张浩雨: extends -> handleSearchOrigin -> this.queryFormCurrent ', 'font-size:16px;background-color:#73b247;color:white;', {...this.queryFormCurrent})
      this.annexConfig.searchApi && this.annexConfig.searchApi.request({
        ...this.queryFormCurrent
      }).then((res) => {
        if (res.status && res.data) {
          let list = res.data;
          if (typeof this.dataTransform === 'function') {
            list = this.dataTransform(list) // ✔ 修复赋值问题
          }
          this.list = list
          this.handleEventHandler({
            event: type,
            data: this.list,
            extraParams: {
              dataSource: this.list
            }
          })
        }
      })
    },
    // ✅ 步骤3:初始化调用/手动调用 完全不变
    initLoad() {
      // 初始化加载数据
      this.handleSearch('load')
    },
    onFileDelete() {
      // 删除后刷新
      this.handleSearch('refresh')
    }
  },
  mounted() {
    this.initLoad()
  }
}

✔ 方案二的核心优点

✅ 绝对无 this 问题:created 里初始化的防抖,this 指向 100% 正确;

✅ Vue2 官方推荐:符合 Vue2 的组件实例生命周期规范;

✅ 可复用性高:防抖逻辑和业务逻辑完全解耦;

✅ 补充:初始化调用防抖方法的【最佳实践】(避免初始化也防抖 300ms)

初始化加载数据需要「立即执行,不需要防抖」,而手动搜索 / 删除后刷新需要防抖,结合你的代码,给你补充这个最佳实践,锦上添花,让体验更好:

✔ 优化点:防抖函数新增「立即执行」参数,初始化无防抖,手动操作有防抖

js 复制代码
// 优化你的全局防抖函数(新增immediate参数)
function debounce(func, delay = 300, immediate = false) {
  let timer: any = null;
  return function(this: any, ...args: any[]) {
    if (timer) clearTimeout(timer);
    // 立即执行:初始化专用,无延迟,直接执行
    if (immediate) {
      func.apply(this, args);
      timer = null;
    } else {
      // 延迟执行:手动操作专用,防抖生效
      timer = setTimeout(() => {
        func.apply(this, args);
        timer = null;
      }, delay);
    }
  };
}

// 初始化赋值不变
this.handleSearch = debounce(function(type = 'load') {
  this.handleSearchOrigin(type)
}, 300)

// ✅ 初始化调用:传true,立即执行,无防抖,秒加载数据
mounted() {
  this.handleSearch('load', true)
}

// ✅ 手动调用:不传true,默认防抖,原有逻辑不变
this.handleSearch('load')

✅ 总结:为什么会踩这个坑?(避坑指南,以后不会再犯)

❌ Vue2 里绝对不能做的 3 件事(防抖相关)

  1. 不要在组件内用 xxx = debounce(()=>{},300) 定义防抖方法 → 箭头函数的 this 指向错误;
  2. 不要在methods里用箭头函数定方法 → 同理,this 指向父级作用域,拿不到 Vue 实例的变量;
  3. 不要在created之前的钩子初始化防抖 → 组件实例还没挂载完成,this 指向错误;
    ✅ Vue2 里防抖方法的【正确打开方式】(2 种,任选其一)
  4. 【极简】赋值式定义:xxx = debounce(function(){},300) → 普通 function 即可;
  5. 【推荐】created 里初始化:在 created 钩子中赋值防抖方法,最稳妥;

✅ 最终结论

问题就是 「箭头函数导致的 this 指向丢失」,按方案一改 1 行代码(箭头函数→普通 function),就能100% 根治,this.queryFormCurrent 会立刻拿到正确的值,所有逻辑恢复正常。

这个坑是 Vue2 + TS 开发中高频踩坑点,记住这个规则:Vue2 里所有需要访问 this 的函数,都不要用箭头函数定义,以后就再也不会遇到类似的问题了 ✔️

Vue2 开发中【100% 会遇到的 8 大类 this 指向问题】

全部整理出来,包含:场景 + 错误写法 + 正确写法 + 原理,按「开发出现频率」排序,你的项目里当前就存在多个这种问题,看完彻底根治所有 this 相关 bug,以后再也不会踩坑!

补充:所有场景的错误核心共性:使用了【箭头函数】 或 函数被「单独抽离调用」/「定时器 / 事件绑定」劫持了 this,这是 Vue2 this 问题的两大元凶。

✨ 前置必懂:Vue2 中 this 的核心规则(记牢这 2 句,终身受用)

Vue2 的methods、watch、computed、生命周期钩子(created/mounted)中,用「普通 function」定义,this 永远指向【Vue 组件实例】 ✔️

箭头函数 ()=>{} 没有自己的this,它的this是「定义时绑定的父级作用域 this」,永远不会指向 Vue 实例 ❌ (Vue2 中绝对的禁区!)

一、【你刚踩的坑,TOP1 高频】防抖 / 节流函数 中的 this 指向问题(⭐⭐⭐⭐⭐)

✅ 出现场景

封装防抖 / 节流函数,赋值给组件方法,实现搜索防抖、按钮防连点、列表刷新防抖(你的业务场景)

✅ 错误写法(你之前的代码,必出问题)

js 复制代码
// ❌ 错误:赋值式+箭头函数,this指向父级作用域,拿不到queryFormCurrent
```js
handleSearch = debounce((type = 'load') => { 
  this.handleSearchOrigin(type) // this ❌ 指向非Vue实例 → queryFormCurrent为空
}, 300)

✅ 正确写法(2 种,你已验证有效)

js 复制代码
// ✅ 写法1:箭头函数 → 普通function,零入侵,只改一行,最推荐
handleSearch = debounce(function(type = 'load') { 
  this.handleSearchOrigin(type) // this ✔️ 指向Vue实例
}, 300)
// ✅ 写法2:在created中初始化防抖,Vue2官方推荐,最稳妥
created() {
  this.handleSearch = debounce(function(type) {
    this.handleSearchOrigin(type)
  },300)
}

✅ 原理

防抖函数内部返回的函数,如果是箭头函数,this绑定的是「防抖函数定义时的父级作用域」,不是 Vue 实例;普通 function 的this是「执行时绑定」,执行时会指向调用者(Vue 实例)。

二、【TOP2 高频】定时器 / 延时器 setTimeout/setInterval 中的 this 指向问题(⭐⭐⭐⭐⭐)

✅ 出现场景

接口请求成功后延迟刷新列表、延迟关闭弹窗

轮询请求接口、倒计时功能

初始化时延迟执行某些逻辑

✅ 错误写法(新手必写,99% 踩坑)

js 复制代码
methods: {
  initData() {
    // ❌ 错误1:普通function回调 → this被浏览器劫持,指向 window
    setTimeout(function() {
      this.queryFormCurrent = {name: '测试'} // undefined
      this.getList() // 报错:this.getList is not a function
    }, 1000)
    
    // ❌ 错误2:直接传入methods方法引用 → this指向 window
    setInterval(this.fetchData, 3000)
  },
  fetchData() { this.getList() }
}```
✅ 正确写法(3 种,按优先级排序)
```js
methods: {
  initData() {
    // ✔️ 写法1【最优推荐】:箭头函数回调 → this继承父级,指向Vue实例
    setTimeout(() => {
      this.queryFormCurrent = {name: '测试'}
      this.getList() // ✅ 一切正常
    }, 1000)
    
    // ✔️ 写法2【万能兜底】:保存_this=this,所有场景通用
    const _this = this
    setInterval(function() {
      _this.fetchData() // ✅ 用_this替代this,永远正确
    }, 3000)
    
    // ✔️ 写法3【优雅简洁】:bind(this)强制绑定Vue实例
    setTimeout(function() {
      this.getList()
    }.bind(this), 1000)
  }
}

✅ 原理

setTimeout/setInterval是浏览器全局 API,会强制把「普通 function 回调」的this绑定到window;对箭头函数无效,因为箭头函数的this定义时就定死了。

✅ 重要注意【必看】:箭头函数的「使用禁区」

❗️ 这是 Vue2 中推荐使用箭头函数的场景,但有严格的使用条件,满足条件才可用,否则必出问题:

✔️ 可用场景:定时器直接定义在 methods/created/mounted 等 Vue 钩子中,父级作用域的 this 是 Vue 实例;

❌ 禁用场景:定时器的回调函数是「抽离的独立方法」「防抖 / 节流包装的方法」「传参给子组件的方法」,此时箭头函数的 this 会指向父级作用域,大概率不是 Vue 实例;

如果定时器是直接在 Vue 的 methods / 生命周期钩子中定义,父级作用域的 this 就是 Vue 实例,那么箭头函数内部的 this 也会指向 Vue 实例。

三、【TOP3 高频】事件监听 / 原生 DOM 事件 中的 this 指向问题(⭐⭐⭐⭐)

✅ 出现场景

给原生 DOM 绑定事件(如addEventListener):监听滚动、窗口大小变化、文件上传、画布绘制

第三方插件的回调事件(如 echarts 的点击事件、富文本编辑器的回调)

✅ 错误写法

js 复制代码
mounted() {
  // 监听窗口大小变化
  window.addEventListener('resize', function() {
    this.$refs.table.doLayout() // this ❌ 指向window → 报错
  })

  // echarts点击事件回调
  this.chart.on('click', () => {
    this.selectData() // this ❌ 指向父级作用域 → 拿不到Vue方法
  })
}

✅ 正确写法

js 复制代码
mounted() {
  // ✅ 写法1:保存_this,万能方案
  const _this = this
  window.addEventListener('resize', function() {
    _this.$refs.table.doLayout() // ✔️ 正确
  })

  // ✅ 写法2:bind绑定this
  this.chart.on('click', function() {
    this.selectData()
  }.bind(this)) // ✔️ 强制绑定Vue实例

  // ✅ 写法3:组件销毁时移除监听,避免内存泄漏(必做!)
  this.resizeHandler = function() {
    this.$refs.table.doLayout()
  }.bind(this)
  window.addEventListener('resize', this.resizeHandler)
},
beforeDestroy() {
  window.removeEventListener('resize', this.resizeHandler)
}

✅ 原理

原生 DOM 事件的回调函数,this 默认指向触发事件的 DOM 元素 / 全局 window,第三方插件的回调同理,都需要手动绑定 Vue 实例的 this。

四、【TOP4 高频】数组遍历 / 高阶函数 forEach/map/filter/reduce 中的 this 指向问题(⭐⭐⭐⭐)

✅ 出现场景

接口返回数组后,遍历处理数据,在遍历回调中调用 Vue 的方法 / 访问 Vue 的变量(你的代码里就有这个场景!)

✅ 错误写法(90% 的新手踩坑)

js 复制代码
methods: {
  formatList() {
    this.list.forEach((item) => {
      item.name = this.$t(item.name) // this ❌ 箭头函数 → 指向父级
    })

    // ❌ 普通function也会丢this
    this.list.map(function(item) {
      return { ...item, status: this.getStatus(item.status) } // this ❌ 指向window
    })
  }
}

✅ 正确写法(3 种)

js 复制代码
methods: {
  formatList() {
    // ✅ 写法1:forEach/map的第二个参数,直接传this,Vue2最优解!
    this.list.forEach((item) => {
      item.name = this.$t(item.name) // ✔️ 正确
    }, this) // ✅ 关键:第二个参数绑定Vue的this

    // ✅ 写法2:保存_this变量
    const _this = this
    this.list.map(function(item) {
      return { ...item, status: _this.getStatus(item.status) }
    })

    // ✅ 写法3:bind绑定this
    this.list.filter(function(item) {
      return item.id === this.selectedId
    }.bind(this))
  }
}

✅ 原理

数组的forEach/map/filter/reduce等高阶函数,回调函数的默认 this 指向 window;这类函数都提供了第二个参数,可以手动传入要绑定的 this,这是 Vue2 中处理数组遍历 this 的最优解。

五、【绝对禁区,新手必踩】methods中用箭头函数定义方法(⭐⭐⭐⭐)

✅ 出现场景

在 Vue 的methods里,用箭头函数定义业务方法(如查询、删除、提交)

✅ 错误写法(绝对禁止! 写了必出问题)

js 复制代码
methods: {
  // ❌ 错误:箭头函数定义methods方法,this永远指向父级作用域
  getList: () => {
    this.annexConfig.searchApi.request({...this.queryFormCurrent}) // this ❌ 全部报错
  },
  // ❌ 同上,删除方法也会丢this
  deleteItem: () => {
    this.$confirm('确定删除?').then(() => {})
  }
}

✅ 正确写法(唯一正确写法)

js 复制代码
methods: {
  // ✅ 必须用普通function定义methods方法
  getList() {
    this.annexConfig.searchApi.request({...this.queryFormCurrent}) // ✔️ 正确
  },
  deleteItem() {
    this.$confirm('确定删除?').then(() => {})
  }
}

✅ 原理

Vue2 的methods会把所有方法挂载到 Vue 实例上,并自动绑定 this 指向 Vue 实例;如果用箭头函数,方法的 this 不会被 Vue 劫持,永远指向父级作用域,导致所有this.xxx都拿不到值。

六、【高频坑】watch/computed中用箭头函数(⭐⭐⭐⭐)

✅ 出现场景

监听变量变化(如queryFormCurrent的变化)、计算属性中处理数据,这两个选项是 Vue2 的核心,用错直接崩盘

✅ 错误写法

js 复制代码
watch: {
  // ❌ 错误:箭头函数,this指向父级,拿不到Vue实例
  queryFormCurrent: (newVal) => {
    this.handleSearch('load') // this ❌ 报错
  }
},
computed: {
  // ❌ 错误:箭头函数,无法访问data中的变量
  totalCount: () => {
    return this.list.length // this ❌ undefined
  }
}

✅ 正确写法

js 复制代码
watch: {
  // ✅ 普通function,this指向Vue实例
  queryFormCurrent(newVal) {
    this.handleSearch('load') // ✔️ 正确
  }
},
computed: {
  // ✅ 普通function,唯一正确写法
  totalCount() {
    return this.list.length // ✔️ 正确
  }
}

✅ 原理

和methods一样,Vue2 会对watch和computed的函数做自动 this 绑定,只有普通 function 才能被劫持,箭头函数则完全无效。

七、【异步场景】Promise/async/await/ 接口请求回调 中的 this 指向问题(⭐⭐⭐)

✅ 出现场景

axios/request 接口请求的then/catch回调、Promise 的回调函数、async/await 中处理异步逻辑(你的代码里大量用到!)

✅ 错误写法

js 复制代码
methods: {
  async getList() {
    // ❌ 错误1:then回调中用普通function,this指向window
    this.annexConfig.searchApi.request({...this.queryFormCurrent})
      .then(function(res) {
        this.list = res.data // this ❌ 报错
      })

    // ❌ 错误2:catch回调箭头函数,this指向父级
    axios.get('/api/list', {params: this.queryFormCurrent})
      .catch(() => {
        this.$message.error('请求失败') // this ❌ 可能丢失
      })
  }
}

✅ 正确写法(3 种,按优先级)

js 复制代码
methods: {
  async getList() {
    // ✅ 写法1:async/await 最推荐!异步代码同步化,完全无this问题
    const res = await this.annexConfig.searchApi.request({...this.queryFormCurrent})
    this.list = res.data // this ✔️ 绝对正确

    // ✅ 写法2:then回调用箭头函数,简洁(Vue2中唯一推荐用箭头函数的场景!)
    this.annexConfig.searchApi.request({...this.queryFormCurrent})
      .then(res => {
        this.list = res.data // ✔️ 正确
      })

    // ✅ 写法3:bind绑定this
    axios.get('/api/list')
      .then(function(res) {
        this.list = res.data
      }.bind(this))
  }
}

✅ 重要补充 ✨

这是 Vue2 中「唯一推荐使用箭头函数」的场景!

Promise 的then/catch/finally回调中,用箭头函数不会导致 this 丢失,反而会继承父级作用域的 Vue 实例 this,这是箭头函数的正确用法,也是 ES6 的最佳实践。

八、【冷门但致命】组件传参 / 回调函数 中的 this 指向问题(⭐⭐⭐)

✅ 出现场景

父组件给子组件传方法回调(如子组件点击按钮,调用父组件的刷新方法)、子组件 emit 事件后父组件的回调处理

✅ 错误写法

js 复制代码
<!-- 父组件 -->
<child-component :onRefresh="handleSearch" />

<script>
export default {
  methods: {
    handleSearch() {
      this.getList() // this ✔️ 父组件中调用正常
    }
  }
}
</script>

<!-- 子组件 -->
<button @click="props.onRefresh()">刷新</button>
<script>
export default {
  props: ['onRefresh'],
  methods: {
    init() {
      // ❌ 错误:子组件中调用父组件传的方法,this指向子组件实例
      this.props.onRefresh() 
    }
  }
}
</script>

✅ 正确写法

ts 复制代码
<!-- 父组件:传参时绑定this,核心! -->
<child-component :onRefresh="handleSearch.bind(this)" />

<!-- 或父组件中用箭头函数封装回调 -->
<child-component :onRefresh="() => this.handleSearch()" />

<!-- 子组件调用即可 -->
<button @click="props.onRefresh()">刷新</button>

✅ 原理

父组件传递的方法,在子组件中调用时,this 默认指向子组件实例,需要在父组件传参时,用bind(this)强制绑定父组件的 Vue 实例。

✨ 终极补充:【Vue2 this 指向问题的万能解决方案】(所有场景通用,记这 3 个,走遍天下都不怕)

不管遇到任何 this 指向丢失的场景,以下 3 种方案全部能解决,按优先级排序,无脑用即可:

✅ 方案 1:保存_this = this (万能兜底,最简单,无任何学习成本)

js 复制代码
const _this = this; // 保存Vue实例的this
// 任何回调函数中,用_this代替this即可
setTimeout(function() {
  _this.getList()
},1000)

✅ 方案 2:用bind(this) 绑定 Vue 实例(简洁优雅,适合函数回调)

js 复制代码
setTimeout(function() {
  this.getList()
}.bind(this),1000)

✅ 方案 3:用箭头函数(仅适用于 Promise/async/await 的回调,唯一合法场景)

js 复制代码
axios.get('/api/list').then(res => {
  this.list = res.data // ✔️ 正确
})

✅ 总结:Vue2 this 指向问题【避坑总纲】(一句话记全,永不踩坑)

「普通函数保 this,箭头函数丢 this;定时器存_this,Promise 用箭头;防抖节流改 function,传参回调要 bind」

✅ 所有场景的【错误红线】(绝对不要碰)

❌ methods/watch/computed/ 生命周期钩子,绝对不能用箭头函数;

❌ 防抖 / 节流函数内部,绝对不能用箭头函数定义回调;

❌ 定时器 / 原生事件回调,不绑定 this 就直接用this;

✅ 所有场景的【正确准则】(绝对正确)

✔️ 所有需要访问this.xxx的地方,优先用「普通 function」;

✔️ 异步 Promise 回调,优先用「箭头函数」;

✔️ 任何拿不准的场景,直接用「保存_this」方案,绝对不会错。

你的项目里当前用到了:防抖、数组遍历、接口请求 Promise、组件传参 这 4 个高频场景,看完这篇后,所有 this 相关的 bug 都会被根治,以后写 Vue2 代码再也不会遇到this.queryFormCurrent为空、this.getList报错这类问题了 ✔️

希望这份整理能帮你彻底解决问题,也能帮你夯实 Vue2 的核心基础! 🚀

相关推荐
mldong1 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排2 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60613 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角4 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!4 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰4 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi6 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen6 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马7 小时前
AI源码分析:拆解模型底层实现逻辑
前端
BillKu7 小时前
全局样式变量:CSS 自定义属性(--border-color)和SCSS 变量($border-color)的说明
javascript·css·scss