Search code examples
vue.jseventsconstants

How Vue's event can change const variable is possible?


How Vue's event can change const variable is possible?

The 'state' is the primitive const variable. Of course, it is impossible to change the value.

error: state ++

However, there is no error when increasing the state through the inline event.

Why is that?

https://codepen.io/quietjun/pen/gOvEjvq?editors=1111

<!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>
<script src="https://unpkg.com/vue@3"></script>
<script>
    const { createApp } = Vue;

    createApp({
        setup() {
            const state = 1;
            // of course below line is error
            //state++;
            const increase = () => {
                state++;
            };

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

Of course state is not reactive. However, using the developer tool, you can see that the value has changed.

enter image description here


Solution

  • return {
      state,
      increase,
    }
    

    is short for

    return {
      state: state,
      increase: increase
    }
    

    In other words, inside <template> you don't interact with the const state from <script>.

    You interact with the template context's properties. Think of it as an object created by merging everything that needs to be exposed to the <template> (e.g: spread return of data, all computed, all methods, spread return of setup, all props, etc...)

    And you can safely write to an object's property, unless it has been defined as writeable: false, which is clearly not the case.

    Simple example:

    const a = 1;
    // a++; => Error: "Uncaught TypeError: Assignment to constant variable"
    
    const b = { 
      a,
      increment() {
        this.a++ // 👈 similar to what you're doing in your handler
      }
    };
    
    b.a++;
    console.log(b.a); // 2! no error.
    
    b.increment();
    console.log(b.a); // 3! no error.

    Additionally, @click="expression" is wrapped in an anonymous function by Vue if expression is not callable (akin to @click="() => { expression; }").


    Side note: In your example, if you want state to be reactive you have to declare it as const state = ref(1). Otherwise, even though state++ will change state's value, it won't trigger a re-render, so it will look like it didn't update, until something else triggers a component re-render and the template value gets updated (overridden).