×

Vue3为啥要调整this的逻辑?

提问者:Terry2025.05.24浏览:333

做Vue项目的时候,很多从Vue2转过来的同学都会纠结:Vue3里还能像Vue2那样直接用this吗?这事儿得拆开了说,因为Vue3的设计思路和API变化,让this的用法和地位跟之前大不一样,今天就从变化原因、替代方案、实际场景这些角度,把Vue3里的this讲明白。

Vue2里this几乎是“万能入口”——能拿data里的变量、调用methods里的方法、访问计算属性,还能操作路由和状态管理,但这种设计在复杂组件里容易出问题:this指向不明确(比如在定时器、回调里容易丢指向);Options API靠this把所有东西“串”起来,导致代码逻辑分散(比如一个功能的代码可能分散在datamethodscomputed里),维护起来费劲。

Vue3推出组合式API(Composition API),就是想解决逻辑复用和代码组织的问题,组合式API更强调“函数式”的写法,把相关逻辑聚在一起,这时候再依赖this就不合适了——因为组合式API的函数里,this不一定指向组件实例(比如在setup函数里,thisundefined),所以Vue3通过调整API设计,弱化了this的存在感,用更明确的方式来获取组件资源。

Vue3里怎么替代this的常见用法?

访问组件数据:从this.xxx到响应式API

Vue2里用this.count访问data里的变量,Vue3的组合式API里,得用refreactive先把数据变成响应式,再直接访问,举个例子:

// Vue2写法
export default {
  data() {
    return { count: 0 }
  },
  methods: {
    add() {
      this.count++ // 依赖this
    }
  }
}
// Vue3组合式API写法
import { ref } from 'vue'
export default {
  setup() {
    const count = ref(0) // 用ref创建响应式数据
    const add = () => {
      count.value++ // 直接操作count的value,不需要this
    }
    return { count, add } // 暴露给模板用
  }
}

这里核心是响应式数据的创建和访问方式变了——ref包装后要通过.value访问(模板里不用,JS里得用),reactive包装的对象则可以直接点属性(但要注意深响应式和解构问题)。

调用方法:从this.xxx()到函数作用域

Vue2里调用方法靠this.handleClick(),Vue3组合式API里,方法就是普通函数,定义在哪就从哪调用,比如在setup里定义的函数,直接调用就行:

// Vue3里在setup内调用方法
import { ref } from 'vue'
export default {
  setup() {
    const count = ref(0)
    const add = () => {
      count.value++
      logCount() // 直接调用同作用域的函数
    }
    const logCount = () => {
      console.log(count.value)
    }
    return { add }
  }
}

这种写法更符合JavaScript的函数作用域逻辑,不用再依赖this来“跨区域”找方法,代码的内聚性更强。

访问路由、状态管理等全局对象:用工具函数

Vue2里拿路由要this.$router,拿Vuex要this.$store,Vue3里得换方式:

  • 路由:在组合式API里,用useRouteruseRoute(需要先安装Vue Router 4+)  

    import { useRouter, useRoute } from 'vue-router'
    export default {
      setup() {
        const router = useRouter()
        const route = useRoute()
        const goHome = () => {
          router.push('/') // 替代this.$router.push
        }
        return { goHome }
      }
    }
  • Vuex:用useStore(需要Vuex 4+)  

    import { useStore } from 'vuex'
    export default {
      setup() {
        const store = useStore()
        const fetchData = () => {
          store.dispatch('getData') // 替代this.$store.dispatch
        }
        return { fetchData }
      }
    }

    这种“按需引入”的方式,比Vue2里靠this挂载全局对象更清晰,也避免了this指向混乱的风险。

访问组件实例:getCurrentInstance

如果非要在组合式API里拿到组件实例(比如访问自定义指令、老项目里的this遗留逻辑),Vue3提供了getCurrentInstance方法:

import { getCurrentInstance } from 'vue'
export default {
  setup() {
    const instance = getCurrentInstance()
    // instance相当于Vue2里的this,但要注意:
    // 生产环境下instance可能被树摇优化,某些属性不可用
    // 尽量优先用组合式API的标准方法,少依赖实例
    console.log(instance.proxy) // 类似Vue2的this,能访问props、attrs等
  }
}

但官方不推荐滥用getCurrentInstance,因为这会让代码回到“依赖黑盒实例”的老路,违背组合式API的设计初衷。

Vue3中this完全不能用了吗?

也不是,如果用选项式API(Options API)写Vue3代码,this依然可以用,用法和Vue2几乎一样:

// Vue3选项式API写法
export default {
  data() {
    return { count: 0 }
  },
  methods: {
    add() {
      this.count++ // 这里this还能用
    }
  }
}

Vue3对选项式API做了兼容,所以如果团队更习惯Options API的写法,this的使用方式和Vue2差别不大,但要注意:选项式API里的this,在setup函数中还是undefined(因为setup是在组件实例创建前执行的)。

常见误区:把Vue3的this和Vue2混着用

很多同学刚学Vue3时,容易犯“缝合怪”错误——在setup里试图用this,或者在选项式API里乱入组合式API的写法。

// 错误示范:setup里用this
export default {
  setup() {
    this.count = 1 // 报错!setup里this是undefined
  },
  data() { return { count: 0 } }
}
// 错误示范:选项式API里用ref却忘改.value
export default {
  data() { return { count: ref(0) } }, // 没必要!data里的变量本身就是响应式的
  methods: {
    add() {
      this.count.value++ // 多此一举,选项式API里直接this.count++就行
    }
  }
}

核心要明白:组合式API和选项式API是两套逻辑,别把响应式API和this的用法硬凑在一起,组合式API走“函数式、显式引入”的路子,选项式API保留“this聚合资源”的模式,选一种风格写到底更不容易出错。

Vue3的this,变的是逻辑,不变的是目的

Vue3调整this的用法,不是为了折腾开发者,而是为了让代码更易维护、逻辑更内聚,如果用选项式API,this的体验和Vue2差不多;如果用组合式API,要学会用ref/reactive管理响应式数据,用useRouteruseStore等工具函数替代全局对象访问,用函数作用域替代this的跨域调用。

理解背后的设计逻辑(组合式API的函数式、逻辑聚合),比死记“this还能不能用”更重要,毕竟框架的变化是为了解决实际开发里的痛点,跟着设计思路走,写代码时的困惑自然会少很多~

(延伸思考:如果团队要做Vue2到Vue3的迁移,怎么处理大量依赖this的老代码?可以先从选项式API兼容写法入手,逐步往组合式API重构;或者用Vue3的兼容模式,让老代码先跑起来,再分批优化。)

您的支持是我们创作的动力!

网友回答文明上网理性发言 已有0人参与

发表评论: