0

我只是想将使用内置fetch()方法从 AJAX 调用中获取的数据设置到我的 Vue 组件的数据变量courts中(我正在使用 Vue2)。

我知道当你进入fetch()方法时,关键字的上下文this可能会改变。但是,如果我将变量courts作为道具绑定到我的子组件,它会呈现到 HTML中,但我仍然无法从例如created()mounted()生命周期钩子访问道具。

我已经阅读了这个问题,它指出了关于关键字的问题this

由于 JavaScript 的异步工作流程,我还检查是否使用setTimeout()我做的方法获取数据,但不是在我的子组件中作为道具。

我从 Webpack 加载了 Babel,我试图用一个async await函数对其进行排序,但没有运气。

App.vue(父组件)

<template>
    <div class="container">
        <court-map v-bind:items="courts"></court-map>
        <navbar v-bind:items="courts"></navbar>
    </div>
</template>

<script>
    import CourtMap from './components/CourtMap.vue';
    import Navbar from './components/Navbar.vue';

    export default {
        components: {
            'navbar': Navbar,
            'court-map': CourtMap
        },
        data() {
            return {
                courts: [],
            }
        },
        created() {
            this.getCourts();
        },
        methods: {
            getCourts() {
                let _self = this;
                fetch('/api/courts', {
                    method: 'GET',
                    headers: {
                        'Accept': 'application/json',
                        'Content-type': 'application/json'
                    }
                })
                .then(response => response.json())
                .then(data => {
                    _self.courts = data; // With alias
                    this.courts = data;
                    console.log(_self.courts); // Shows my data
                })
                    .catch(error => console.error(error));

                console.log(_self.courts); // No longer shows my data
                setTimeout(function() {
                    console.log(_self.courts); // Shows my data
                    console.log(this.courts); // Undefined
                }, 3000);
            }
        }
    }
</script>

我也this.$props.items用来访问我的道具,但它给了我一个空数组。

CourtMap.vue(子组件)

编辑:对不起,我忘了this在变量的索引中使用。

<template>
    <div class="map-viewer">
        <div class="esri-widget">
            <camera-info v-bind:camera="camera"></camera-info>
        </div>
        <div>{{ items }}</div> // Renders the prop with the right data
        <div id="viewMap"></div>
    </div>
</template>

<script>
    import { loadModules } from 'esri-loader';

    export default {
        components: {
            'camera-info': CameraInfo
        },
        props: {
            items: {
                type: Array,
                required: true
            },
        },
        data() {
            return {
                firstIndex: 0,
                camera: {
                    position: {
                        longitude: this.items[this.firstIndex].longitude, // Return this is not defined
                        latitude: this.items[this.firstIndex].latitude // Return this is not defined
                    },
                    tilt: 0,
                    heading: 0
                },
            }
        },
        created() {
        },
        methods: {
            createMap() {
               // Some function here
            }
        },
        mounted() {
            console.log(this.items); // Doesn't show the data
            setTimeout(function() {
                console.log(this.items); // Doesn't show the data too
            }, 3000);
            this.createMap();
        },
    }
</script>

Index.js(我开始我的 Vue 应用程序的地方)


import Vue from 'vue';
import App from './App.vue';

new Vue({
    render: h => h(App)
}).$mount('#app');

我想这是新手必须经历的事情,但出于这个原因,我想知道每次我想访问 Vue 中获取的数据时我必须遵循哪种模式。我现在不知道如何进行。

预先感谢您花时间阅读本文。

4

1 回答 1

0

让我们澄清一些事情。

this不只是随机变化。当您输入新功能时,它会发生变化。从历史上看,使用别名self是避免此问题的一种方法,但在您的情况下,您使用的是箭头函数。箭头函数不会更改this周围范围的值。

现在让我们看看为什么这不起作用:

mounted () {
    console.log(this.items); // Doesn't show the data
    setTimeout(function() {
        console.log(this.items); // Doesn't show the data too
    }, 3000);

它第一次尝试访问this.items为时过早。异步fetch还没有完成。

第二次,在 内部setTimeout,我们有了一个新函数,所以this值发生了变化。使用箭头函数应该显示正确的数据:

setTimeout(() => {
    console.log(this.items);
}, 3000);

当然,假设数据在 3 秒内加载。

当然,计时器不是处理这个问题的正确方法。

最简单的选择是在数据可用之前避免创建子组件:

<court-map v-if="courts.length" :items="courts"></court-map>

v-if将阻止创建组件,直到数组中有条目。这样做可以确保created和钩子在准备好作为 传递mounted之前不会运行。courtsitems

也许空数组不是这里初始值的最佳选择,因为除了服务器返回的空数组之外很难分辨。相反,如果我们null最初使用一个更简单的值。

data() {
    return {
        courts: null
    }
},

和:

<court-map v-if="courts" :items="courts"></court-map>

其他使用的代码courts可能需要相应调整。

或者,如果您不想使用v-if来延迟子项的创建,那么您可以watch在子项中使用以等待何时items更改。然后,您可以触发需要发生的任何操作。

关于为什么这条线不起作用的进一步说明:

longitude: this.items[firstIndex].longitude

所以第一个问题是this.items它还没有加载(如上所述)。第二个问题firstIndex是没有定义。它上面的firstIndex: 0几行无关紧要。this.items[firstIndex]正在尝试使用一个名为firstIndex但不存在的局部变量。

在不了解更多信息的情况下,很难说,但position作为计算属性可能会更好地实现。

于 2019-09-14T22:43:38.187 回答