首页 > 解决方案 > 函数完成后的 VueJS 渲染

问题描述

所以我遇到了这个问题:我在 VueJS 中得到了这个组件:

<img v-bind:src="'data:image/jpg;base64,'+ filesData[posts[file.index].id]" class="image" />

这是在 for 指令中

<div v-for="file in files" :key="file.name" style="width: 30%; height: auto;">

所以这里一切都很好。在同一内部,我有一个函数用于为 filesData 数组提供正确的数据。功能如下:

getEachFile: function(id){
  console.log(id)
  setTimeout(function(){}, 500);
  this.axios({
    method: 'get',
    url: 'http://' + this.$store.state.server + ':3000/post/' + id,
    headers:{
      'authorization': this.$store.state.token
    }
  }).then((response) => {
      var bytes = response.data.data.data;
      this.filesData[id] = this.encode(new Uint8Array(bytes), id);
  })
}

所以我正在向我的本地服务器发送一个 HTTP 请求。本地服务正在返回一个包含图像数据的缓冲区。您可以看到在响应承诺中我调用了另一个函数这是该函数(用于转换为 base64)

encode: function(input, id) {
  var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  var output = "";
  var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
  var i = 0;

  while (i < input.length) {
      chr1 = input[i++];
      chr2 = i < input.length ? input[i++] : Number.NaN; // Not sure if the index 
      chr3 = i < input.length ? input[i++] : Number.NaN; // checks are needed here

      enc1 = chr1 >> 2;
      enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
      enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
      enc4 = chr3 & 63;

      if (isNaN(chr2)) {
          enc3 = enc4 = 64;
      } else if (isNaN(chr3)) {
          enc4 = 64;
      }
      output += keyStr.charAt(enc1) + keyStr.charAt(enc2) +
                keyStr.charAt(enc3) + keyStr.charAt(enc4);
  }
  return output;
}

一切都很好,但问题是“img”组件/标签在函数编码完成执行后没有再次呈现。当我在互联网上搜索时,我意识到使用类似的东西:

this.filesData[id] = 'something'

不是强制组件重新渲染,我必须使用那个 Vue.set() 但是使用 Vue.set(),强制重新渲染,创建一个无限循环,函数调用在“for”指令内. 有没有办法用这些值设置 filesData 数组,并且在这些值准备好重新渲染仅“img”组件之后?如果没有,在函数执行后我能做些什么来呈现这些标签?

更新:我在这里完全放了 for 指令

<!--"For" used to display 6 posts. Files variable stores the files from HTTP response.-->
<div v-for="file in files" :key="file.name" style="width: 30%; height: auto;">

  <div>{{getEachFile(posts[file.index].id)}}</div>
  <!--Each post is displayed using a dialog template, so when you click one of the images, a dialog box is open.-->

  <v-dialog
    v-model="dialog[file.index]"
    height="auto"
    max-width="800"
  >
    <!--Here starts the activator for the dialog box. The activator si the entire post.-->
    <template v-slot:activator="{ on, attrs }">
      <!--The following is the entire flex item described by the css from App.vue-->
      <div class="flexitem"
           v-bind="attrs"
           v-on="on"
      >
        <postName :file="file" :posts="posts"/>
        <description :file="file" :posts="posts"/>
        <img v-bind:src="'data:image/jpg;base64,'+ filesData[posts[file.index].id]" class="image" />
      </div>
    </template>

    <dialogBox :file="file" :posts="posts" :filesData="filesData"/>
  </v-dialog>
</div>

标签: functionvue.jsrendering

解决方案


发生这种情况是因为您没有更新数组中的实际file对象。files如果是这种情况,组件将正确重新渲染,因为您已key为每个组件分配了唯一的道具。

在这种情况下,最好的解决方案就是使用forceUpdate. 您可以在全局 ( Vue.forceUpdate()) 或本地调用它,如下所示:

getEachFile: function(id){
  console.log(id)
  setTimeout(function(){}, 500);
  this.axios({
    method: 'get',
    url: 'http://' + this.$store.state.server + ':3000/post/' + id,
    headers:{
      'authorization': this.$store.state.token
    }
  }).then((response) => {
      var bytes = response.data.data.data;
      this.filesData[id] = this.encode(new Uint8Array(bytes), id);
      this.$forceUpdate(); // calling it after encode 
  })
}

有一篇关于强制组件重新渲染的中等帖子。我认为这可能会有所帮助。


推荐阅读