简体   繁体   English

Vue.js 动态组件 - 仅在组件内部获取数据时加载

[英]Vue.js dynamic components - load only when data is fetched inside component

I am implementing Vue.js dynamic components but I can't seem to figure out how to show the component only when it has fetched it's data.我正在实现 Vue.js 动态组件,但我似乎无法弄清楚如何仅在获取数据时才显示该组件。 Until then it should show the old component.在此之前,它应该显示旧组件。

The scenario is this.场景是这样的。 When the page is loaded it should show the Home component.当页面加载时,它应该显示 Home 组件。 Then I click on "Show posts".然后我点击“显示帖子”。 Nothing should happen until the Posts component has fetched it's posts.在 Posts 组件获取它的帖子之前,什么都不应该发生。 Then it should show the Posts component.然后它应该显示 Posts 组件。 I don't want any loading to show.我不想显示任何加载。

I could fetch posts in my Home compoent but I think the Posts component should be responsible for that.我可以在我的 Home 组件中获取帖子,但我认为 Posts 组件应该对此负责。 Also if I have many components I don't want to fetch all their data in my Home component.此外,如果我有很多组件,我不想在我的 Home 组件中获取它们的所有数据。 They should fetch their own data (I think).他们应该获取自己的数据(我认为)。 Is this possible to do?这有可能吗?

home.js主页.js

import Home from './home.js'
import Posts from './posts.js'

export default {
    template: `
        <div>
            <a @click="showPosts">Show posts</a>
            <component :is="currentComponent" />
        </div>
    `,

    methods:
    {
        showPosts()
        {
            // Do this ONLY after the Posts component has fetched it's data... not immediately...
            this.currentComponent = Posts
        }
    },

    data:
    {
        currentComponent: Home
    },
}

posts.js帖子.js

export default {
    template: `
        <div>
            <div v-for="post in posts">{{ post.body }}</div>
        </div>
    `,

    data:
    {
        posts: [],
    },

    created()
    {
        axios.get('/posts').then(({ data } => {
            this.posts = data
        })
    },
}

If you want to show posts component only when posts are fetched, the only way is to fetch data in the parent component . 如果仅在获取帖子时才显示帖子组件, 则唯一的方法是在父组件中获取数据 To do this you normally decouple the fetching from the component. 为此,通常可以将提取操作与组件分离。 You have something like a apiService , which fetches posts and the Posts component really is only the view and its only purpose is displaying data. 您具有类似apiService ,该功能可获取帖子,而Posts组件实际上只是视图,其唯一目的是显示数据。 This way your code also becomes much more re-usable, since many api requests probably share a lot of logic. 这样,您的代码也变得更加可重用,因为许多api请求可能共享很多逻辑。

Here is how your component could look like: 这是您的组件的外观:

home.js home.js

import Home from './home.js'
import Posts from './posts.js'
import apiService from '../services/apiService.js'

export default {
    template: `
        <div>
            <a @click="showPosts">Show posts</a>
            <component :posts="posts" :is="currentComponent" />
        </div>
    `,

    methods:
    {
        showPosts()
        {
            apiService.fetchPosts().then((response) => {
                this.posts = response.data.posts
                this.currentComponent = Posts
            });
        }
    },

    data:
    {
        posts: []
        currentComponent: Home
    },
}

You can use the async created hook in combination with a v-if statement. 您可以将async created钩子与v-if语句结合使用。

So you basically wrap your template in a v-if 因此,您基本上将模板包装在v-if

template: '<div v-if="dataloaded">This is component xlr</div>

Inside the async created you load your data and set the flag to true once it is finished 在创建的异步内部,加载数据,并在完成后将标志设置为true

  async created() {
  await loadData(3000);
  this.dataloaded = true;},

See a working fiddle here: https://jsfiddle.net/Postlagerkarte/yomb5qv6/ 在此处查看有效的小提琴: https//jsfiddle.net/Postlagerkarte/yomb5qv6/

Your procedure is not really good coding practice. 您的过程并不是很好的编码习惯。

I would recommend you to use Vuex. 我建议您使用Vuex。 It allows you to share states across many components. 它使您可以在许多组件之间共享状态。

Some resources: 一些资源:

What is Vuex? 什么是Vuex?

Vuex State Management Vuex状态管理

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM