首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >用于重新呈现计算属性的Vue.js加载指示器

用于重新呈现计算属性的Vue.js加载指示器
EN

Stack Overflow用户
提问于 2018-06-02 06:15:39
回答 1查看 3K关注 0票数 1

我有一个用Vue.js编写的小型web应用程序,我正在尝试在页面上显示一个加载指示器,同时项目列表正在被过滤和重新呈现。该列表不是异步获取的,它只是基于某些筛选器字段的计算属性中的项的列表,并随着筛选器的更改而更新。在UI中更新列表之前有几秒钟的延迟,因为列表大约有1400个项目,并且每个项目都是具有图像、按钮、图标和一些文本的卡式组件。我试图显示一个“正在加载...”过滤器更改和新列表呈现之间的消息,但似乎无法将其显示给用户。

我已经组合了一个简化的小提琴作为示例:https://jsfiddle.net/zm4z9657/1/

编辑:以下是代码片段:

代码语言:javascript
复制
new Vue({
  el: '#app',
  data: {
    even: false,
    loading: false
  },
  computed: {
    numbers: function() {
    	this.rerender();
      return this.even ? _.range(0,100000,2) : _.range(0,100000);
    }
  },
  methods: {
    rerender: function() {
      var self = this;
      
      /* self.loading = true */;
      //this.$nextTick(() => {
      	self.loading = true;
        console.log('re-render start')
        
        this.$nextTick(() => {
          self.loading = false;
          console.log('re-render end')
        })
      //})
    },
  }
})
代码语言:javascript
复制
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/lodash"></script>

<div id="app">
  <input type="checkbox" value="1" v-model="even" /> even?
  <div v-if="loading" id="loading">
    Loading...
  </div>
  <div v-else id="loaded">
    <div>
      <div v-for="number in numbers" :key="number">{{number}}</div>
    </div>
  </div>

</div>

该示例显示数字1-100000的列表,当您单击"even ?“checkbox筛选器,它会导致列表仅使用偶数进行更新。100000用于显示新列表的呈现过程中的轻微延迟。如果检查DOM,可以看到在选中/取消选中复选框后,<div id="loading">会在DOM中弹出一小段时间,然后切换到<div id="loaded">中的新列表。尽管加载的<div>显示在DOM中,但它永远不会在UI中更新。

我有一些代码,我希望在调用computed属性时显示“正在加载”,当列表渲染完成时,隐藏它并显示列表。为什么这不起作用?为什么DOM会改变,但UI永远不会更新?UI没有更新是因为所有动态元素都在同一个组件中,并且在列表渲染完成之前不会刷新它吗?有没有更好的方法来实现这一点?

谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-02 07:29:55

您正在进行一个长时间的同步过程。这些类型的进程占用了UI线程,即您不能在选项卡中执行任何操作,也不能在此期间更新DOM。

要像你这样做很长的过程,你应该把它放到一个Web Worker中。使用消息传递api,您将向worker发送一条消息,告诉它创建列表,并在完成后发送回一条消息。这将使您的流程异步,而不会占用UI。

附注:您可能需要考虑使用分页来显示如此大的列表。因为隐藏/显示那么多元素也会导致浏览器锁定。

html

代码语言:javascript
复制
<input type="checkbox" value="1" v-model="even" @change="onEvenChanged" /> even?

worker.js

代码语言:javascript
复制
importScripts("lodash.js");

self.addEventListener('message', function(e) {
  var data = e.data;
  if(data.command == "start"){
    let list = data.even ? _.range(0,100000,2) : _.range(0,100000);
    self.postMessage({"list":list});
  }
}, false);

app.js

代码语言:javascript
复制
var app,msgBus;
var worker = new Worker('worker.js');

//listen for messages coming back from the worker
worker.addEventListener('message', function(e) {
  var data = e.data;
  if(data.list){
    //emit a message to your vue app that the list
    //was made
    msgBus.$emit('listGenerated',data.list);
  }
}, false);

//separate empty vue for events
msgBus = new Vue();

app = new Vue({
        el: '#app',
        mounted:function(){
          //Listen for a listGenerated event
          //set numbers to the passed list
          msgBus.$on("listGenerated",(list)=>{
            this.numbers = list;
            this.loading = false;
          });
        },
        methods:{
          onEvenChanged:function(){
            this.loading = true;
            //send the start command to the worker
            //passing also the even property
            this.$nextTick(()=>{
              worker.postMessage({command:"start",even:this.even});
            });
          }
        }
      });

Demo on plunker

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50651601

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档