Home > Mobile >  In VueJs3 why can't I access data properties from the vue object? (it worked in Vue2)
In VueJs3 why can't I access data properties from the vue object? (it worked in Vue2)

Time:03-30

Background

I've been using Vue 2 for a long time and am currently exploring Vue 3 to see what converting our existing website will entail. Because this is a conversion I plan to use the options interface for Vue 3. For the most part it seems like the conversion should be fairly painless. But I have encountered one Vue3 behavior that I find very puzzling.

Vue 2 Example

In Vue 2 if I have the following code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>
</head>
<body>
    <h1>Vue2 app.variable example</h1>

    <!-- vue template -->
    <div id="appTemplate">
        <div style="margin-bottom:20px">Count: <span v-text="count"></span></div>
        <button v-on:click="increment()">Increment</button>
    </div>

    <script type="text/javascript">
        //Vue2 Example 
        var app = new Vue({
                el: '#appTemplate',
                data: {
                    count: 101
                },
                methods: {
                    increment: function() {
                        this.count  ;
                    }
                },
                created: function(){
                    _app = this;
                }
            });

        alert("app.count is:"   app.count)

    </script>
</body>
</html>

When the page loads, the alert looks like this:

vue 2 app.count alert

This demonstrates that after the vue object is created I can access the data properties as though they hang directly off of the vue object. This is as expected since it's documented behavior.

However, Vue 3 Behaves Differently for Me

Here is a block of analogous Vue3 code with a bit of extra code you will probably notice:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.global.js"></script>
</head>
<body>
    <h1>Vue3 app.variable example</h1>

    <!-- vue template -->
    <div id="appTemplate">
        <div style="margin-bottom:20px">Count: <span v-text="count"></span></div>
        <button v-on:click="increment()">Increment</button>
    </div>

    <script type="text/javascript">
        //Vue3 OptionsAPI 
        var _app;
        var app = Vue.createApp({
                data: function() {
                    return {
                        count: 101
                    }
                },
                methods: {
                    increment: function() {
                        this.count  ;
                    }
                },
                created: function(){
                    _app = this;
                }
            }
            
        );
        app.mount("#appTemplate");

        //It's really odd that we can't access the property this way:
        alert("app.count is:"   app.count);

        //but this works.
        alert("_app.count is:"   _app.count);

    </script>
</body>
</html>

When this page loads and the first alert box is shown, app.count is undefined.

Vue 3 app.count alert

To explore this a bit more you can see in the code that I set the value of an _app variable to the value of this in the created method. And I show a 2nd alert on load that displays _app.count. And sure enough that works and displays the correct value:

Vue3 _app.count alert

So that's pretty interesting. Is it by design in Vue 3 data properties can't be accessed directly from the vue object or is something wrong with my code? It seems like a really big change from Vue 2 if it's by design. So I'd like to hope that it's not.

So here is the question: Why can't I access count via app.count after the var app = Vue.createApp ?

CodePudding user response:

In Vue 2, new Vue() returns the root component.

In Vue 3, createApp() returns the application instance, and the root component is returned from the application instance's mount():

var app = Vue.createApp({
  data() {
    return {
      count: 101,
    }
  }
})
                
  • Related