如何仅在准备就绪时使元素渲染?

时间:2019-04-29 01:29:44

标签: javascript vue.js vuejs2

当我向api发送请求并将结果呈现为列表时,某些图像显示较晚,而文本首先显示。有什么办法可以防止这种情况?
我只想在逻辑上完全完成图像,类,文本的计算时显示列表。如果它们还没准备好,我还是要隐藏它们。 v-cloak 无法正常工作!。

这是我遇到麻烦的部分。

enter image description here

您可以看到,还渲染了整个列表,还剩下一些图像。

这是我的代码示例。

    <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/

在jsfiddle上面没有清楚显示我的问题,因为它没有发送到真实的api且渲染速度太快。

2 个答案:

答案 0 :(得分:1)

您可以使用v-if仅在requestApi完成时显示组件:

<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
      }
  }
})

请注意,isLoading用作检查请求是否完成的标志。

答案 1 :(得分:1)

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;
     })
}