Mg Mg Tint
Mg Mg Tint

Reputation: 243

How to make render the elements only when they are ready in vue?

When I send a request to api and render the result as a list, some images are showing late and text are rendered first. Is there any way to prevent this?
I want to show the list only when images, classes, text are totally finished computing by logic. If they are not ready, I want to still hide them. v-cloak is not working!.

This is the part I'm getting trouble.

enter image description here

You can see, also the entire list is rendered, there are some images left.

Here is my code example.

    <div id="app">
    <h2>Todos:</h2>
    <ol>
        <li v-for="todo in todos">
            <!-- thre may be some more logics -->
            <img :src="todo.img" width="100px">
            {{todo.name}}
        </li>
    </ol>
</div>

new Vue({
    el: "#app",
    data: {
        todos: []
    },
    created: function(){
        this.requestApi();
    },
    methods: {
        requestApi(){
        this.todos = [
                { img: "https://steamcdn-a.akamaihd.net/apps/dota2/images/mars/hero_mars93fd33s5.jpg", name: "AAA" },
                { img: "https://steamcdn-a.akamaihd.net/apps/dota2/images/mars/hero_mars93fd33s5.jpg", name: "BBB" },
                { img: "https://steamcdn-a.akamaihd.net/apps/dota2/images/mars/hero_mars93fd33s5.jpg", name: "CCC" },
                { img: "https://steamcdn-a.akamaihd.net/apps/dota2/images/mars/hero_mars93fd33s5.jpg", name: "DDD" }
            ];
        }
    }
})

https://jsfiddle.net/vxy4gnj8/3/

It's not showing clearly my problem in above jsfiddle because it's not sending to a real api and rendered too fast.

Upvotes: 0

Views: 979

Answers (2)

ashe
ashe

Reputation: 127

requestApi(){
    const vm = this;
    const list = [
      { img: "https://steamcdn-a.akamaihd.net/apps/dota2/images/mars/hero_mars93fd33s5.jpg", name: "AAA" },
      { img: "https://steamcdn-a.akamaihd.net/apps/dota2/images/mars/hero_mars93fd33s5.jpg", name: "BBB" },
      { img: "https://steamcdn-a.akamaihd.net/apps/dota2/images/mars/hero_mars93fd33s5.jpg", name: "CCC" },
      { img: "https://steamcdn-a.akamaihd.net/apps/dota2/images/mars/hero_mars93fd33s5.jpg", name: "DDD" }
    ];

    Promise.all(
        list.map(item=>new Promise((resolve,reject)=>{
            const img = new Image();
            img.addEventListener("load",function(){
                // here this means the img element
                this.__isOK__ = true;
                resolve(this);
            },{once:true})
            img.addEventListener("error",function(){
                this.__isOK__ = false;
                resolve(this);
            },{once:true});

            img.src = item.img;
        }))
     ).then(arr=>{
        const success = arr.filter(img=>img.__isOK__);
        console.log(`Finish. We had loaded ${arr.length} pictures. ${success.length} of them was successed`);

        vm.todos = list;
     })
}

Upvotes: 1

ittus
ittus

Reputation: 22393

You can use v-if to only show component when requestApi finished:

<div id="app">
  <div v-if="!isLoading">
    <h2>Todos:</h2>
    <ol>
        <li v-for="todo in todos">
            <!-- thre may be some more logics -->
            <img :src="todo.img" width="100px">
            {{todo.name}}
        </li>
    </ol>
  </div>

</div>

new Vue({
  el: "#app",
  data: {
      todos: [],
      isLoading: true
  },
  created: function(){
      this.requestApi();
  },
  methods: {
      requestApi(){
        this.todos = [
          { img: "https://steamcdn-a.akamaihd.net/apps/dota2/images/mars/hero_mars93fd33s5.jpg", name: "AAA" },
          { img: "https://steamcdn-a.akamaihd.net/apps/dota2/images/mars/hero_mars93fd33s5.jpg", name: "BBB" },
          { img: "https://steamcdn-a.akamaihd.net/apps/dota2/images/mars/hero_mars93fd33s5.jpg", name: "CCC" },
          { img: "https://steamcdn-a.akamaihd.net/apps/dota2/images/mars/hero_mars93fd33s5.jpg", name: "DDD" }
        ];
        this.isLoading = false
      }
  }
})

Note that isLoading is used as a flag to check if request finishes or not.

Upvotes: 1

Related Questions