函数完成后的 VueJS 渲染
VueJS rendering after a function finish
所以我遇到了这个问题:
我在 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;">
所以这里一切都很好。在同一个 for 中,我有一个函数用于为 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' component/tag 在函数编码完成执行后没有再次呈现。
当我在互联网上搜索时,我意识到使用类似的东西:
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>
发生这种情况是因为您没有更新 files
数组中的实际 file
对象。如果是这种情况,组件将 re-render 正确,因为您已为每个组件分配了唯一的 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
})
}
有一个 medium post 关于强制组件 re-render。我认为这可能会有所帮助。
所以我遇到了这个问题: 我在 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;">
所以这里一切都很好。在同一个 for 中,我有一个函数用于为 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' component/tag 在函数编码完成执行后没有再次呈现。 当我在互联网上搜索时,我意识到使用类似的东西:
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>
发生这种情况是因为您没有更新 files
数组中的实际 file
对象。如果是这种情况,组件将 re-render 正确,因为您已为每个组件分配了唯一的 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
})
}
有一个 medium post 关于强制组件 re-render。我认为这可能会有所帮助。