在 VueJs3 中,为什么我不能从 vue 对象访问数据属性? (它在 Vue2 中有效)

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

背景

我使用 Vue 2 已经很长时间了,目前正在探索 Vue 3 以了解转换我们现有网站需要做些什么。因为这是一个转换,所以我计划使用 Vue 3 的选项界面。在大多数情况下,转换似乎应该是相当轻松的。但是我遇到了一个我觉得很费解的 Vue3 行为。

Vue 2 示例

在 Vue 2 中,如果我有以下代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <script src="https://unpkg.com/vue@2.5.16/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>

页面加载时,警报如下所示:

这表明在创建 vue 对象后,我可以访问数据属性,就好像它们直接挂在 vue 对象上一样。这是预期的,因为它记录了行为。

但是,Vue 3 对我来说表现不同

这是一段类似的 Vue3 代码,其中包含一些您可能会注意到的额外代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <script src="https://cdn.jsdelivr.net/npm/vue@3.0.5/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>

加载此页面并显示第一个警告框时,app.count 未定义。

为了进一步探索这一点,您可以在代码中看到我在 created 方法中将 _app 变量的值设置为 this 的值。我显示了第二个负载警报,显示 _app.count。果然可以正常工作并显示正确的值:

这很有趣。是 Vue 3 数据属性无法直接从 vue 对象访问还是我的代码有问题?如果是设计使然,这似乎是 Vue 2 的一个非常大的变化。所以我希望它不是。

所以问题来了: 为什么我不能在 var app = Vue.createApp 之后通过 app.count 访问 count

您还可以在安装应用程序之前访问 属性 :

 app._component.data().count

在 Vue 2 中,new Vue() returns 根组件。

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

var app = Vue.createApp({
  data() {
    return {
      count: 101,
    }
  }
})
     
var root = app.mount('#appTemplate')
console.log(root.count) // => 101

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <script src="https://cdn.jsdelivr.net/npm/vue@3.0.5/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 = Vue.createApp({
                data: function() {
                    return {
                        count: 101
                    }
                },
                methods: {
                    increment: function() {
                        this.count++;
                    }
                },
                created: function(){
                    _app = this;
                }
            }
            
        );
        var root = app.mount("#appTemplate");

        alert("root.count is:" + root.count);


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

或者,您可以将 mount() 调用链接到 createApp():

var app = Vue.createApp().mount('#appTemplate')
console.log(app.count) // => 101

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <script src="https://cdn.jsdelivr.net/npm/vue@3.0.5/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 = Vue.createApp({
                data: function() {
                    return {
                        count: 101
                    }
                },
                methods: {
                    increment: function() {
                        this.count++;
                    }
                },
                created: function(){
                    _app = this;
                }
            }
            
        ).mount("#appTemplate");

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


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