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

Vue3内联事件为何可修改const声明的原始类型变量?

为何Vue的事件能够修改const声明的变量?

问题现象

  • 代码中的state是原始类型const变量,按照JavaScript语法规则,直接执行state++修改其值本应抛出错误,将该逻辑写在increase方法中点击触发同样会报错。
  • 但将state++直接写为按钮的@click内联事件逻辑时,触发无任何报错,通过开发者工具可观测到state值确实发生了变化(该变量并未做响应式处理)。

复现代码

HTML

<!DOCTYPE html>
<html lang="ko">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>모두의 코딩</title>
    </head>
    <body>
        <div id="app">
            <span>{{state}}</span><br />
            <button @click="state++">inline</button><br />
            <button @click="increase">function</button><br />
        </div>
    </body>
</html>

JavaScript

<script src="https://unpkg.com/vue@3"></script>
<script>
    const { createApp } = Vue;

    createApp({
        setup() {
            const state = 1;
            // 下方代码直接执行会抛出错误
            //state++;
            const increase = () => {
                state++;
            };

            return {
                state,
                increase,
            };
        },
    }).mount("#app");
</script>

现象截图

内联事件触发后state值更新截图

产生原因

这个现象和JavaScript的const语法规则没有任何冲突,核心原因是模板内联表达式的作用域和setup函数内部的作用域不是同一个:

  • 你在setup函数里用const声明的state是setup函数作用域内的常量,increase方法作为setup内部声明的箭头函数,闭包引用的就是这个作用域内的常量。原始类型的const变量不允许重新赋值,所以点击绑定increase方法的按钮时,执行state++必然会抛出赋值错误。
  • 模板里的表达式访问变量时,从来不会直接读取setup作用域内的变量,Vue会把模板编译成渲染函数,所有模板里的变量访问都会指向组件实例的代理上下文(你可以理解为一个普通的JS对象,setup返回的所有属性都会被挂载到这个对象上)。
  • 你写在@click="state++"里的内联逻辑,最终会被编译器处理成类似function($event) { return this.state++ }的函数,这里的this指向组件实例代理,修改的是代理对象上的state属性——这是个普通的对象属性,根本不是你用const声明的那个常量,自然不会触发const的赋值限制。
  • 你在开发者工具里看到的值变化、页面上{{state}}的更新,本质都是代理对象上的state属性被修改了,setup作用域里最初用const声明的那个值为1的state常量,从头到尾都没有被改动过。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 07:03:16