VueJS 2 重新渲染 Table
VueJS 2 re-rendering Table
我遇到了 VueJS 渲染问题。我正在按 ajax 获取数据。在初始渲染时,table 行渲染正确,但在重新渲染更新的元素时,它没有正确渲染。
这是一张照片:
Rendered Table
如您所见,第 1 行呈现正确。但是在重新渲染的第 2 行中,tds 被反转了。
这是我的代码:
var renderings = new Vue({
el: '#renderings',
data: function () {
return {
hasUnprocessedRenderings: false,
renderings: {}
};
},
methods: {
clearData: function () {
this.renderings = {};
},
updateData: function () {
this.$http.get('http://some-url.com/renderings').then(function (response) {
this.renderings = response.body.renderings;
this.hasUnprocessedRenderings = response.body.hasUnprocessedRenderings;
if (this.hasUnprocessedRenderings) {
setTimeout(this.updateData, 10000);
}
});
}
},
mounted: function() {
this.updateData();
}
});
和我的 html:
<div id="renderings">
<table class="table table-striped table-hover table-bordered" style="margin bottom: 0;">
<thead>
<tr>
<th>Personalisierung</th>
<th>Format</th>
<th>Download</th>
<th></th>
</tr>
</thead>
<tbody>
<template v-for="rendering in renderings">
<tr>
<td>{{rendering.personalizationName}}</td>
<td>{{rendering.renderTypeName}}</td>
<template v-if="rendering.DOCUMENT_URL">
<td><a :href="rendering.DOCUMENT_URL">{{rendering.DOCUMENT_URL}}</a></td>
<td>
<ul class="list-inline" style="margin-bottom: 0;">
<li><a :href="'http://some-url.com?pid='+rendering.PROCESS_ID" title="refresh"><i class="fa fa-refresh" aria-hidden="true"></i></a></li>
<li><a :href="'http://some-url.com?pid='+rendering.PROCESS_ID" title="delete"><i class="fa fa-trash-o" aria-hidden="true"></i></a></li>
</ul>
</td>
</template>
<template v-else>
<td colspan="2" style="text-align: center;">
<i class="fa fa-cog fa-spin fa-fw"></i>
<span>In Bearbeitung..</span>
</td>
</template>
</tr>
</template>
</tbody>
</table>
</div>
所以我的问题是:如何修复该行是否正确重新呈现?
感谢您的帮助。 :-)
编辑#1:
这是一个 jsfiddle,问题也出现在这里:https://jsfiddle.net/dt1kt06g/
似乎这种行为是 Vue 虚拟 DOM 算法优化的副作用。发生更新时,Vue 会尽量减少元素移动,而是重用和修补现有的 DOM 个节点。
当您在数据更新后检查 JSFiddle 中生成的 HTML 时,您会注意到第二个 <tr>
中的最后一个 <td>
仍然具有属性 colspan="2" style="text-align: center;"
,这给了我们一个提示,这个 <td>
元素被错误地从 v-else
中先前呈现的 "In Progress" 单元格中重用了。 (我不确定这是否可以被描述为 Vue 中的错误...)
无论如何,这个问题有一个解决方法:Vue 有一个特殊的 key
属性,它为节点差异算法提供了如何处理元素的提示 (see documentation)。在您的示例中,向 v-else
分支中的 <td>
添加一个密钥就足够了:
<template v-else>
<td colspan="2" style="text-align: center;" :key="rendering.PROCESS_ID">
...
这是您的 JSFiddle 的 fixed version。
问题可能与您使用 this.renderings = {...}
将数据分配给对象的方式有关
要分配对象属性,您应该为每个新值使用 Vue.set(this.renderings, key, value)
,或者 this.renderings = Object.assign({}, this.renderings, newData)
根据您使用的数据的嵌套程度,这可能完美或不完美,您可以在此处找到有关它的更多信息:https://vuejs.org/v2/guide/reactivity.html
我遇到了 VueJS 渲染问题。我正在按 ajax 获取数据。在初始渲染时,table 行渲染正确,但在重新渲染更新的元素时,它没有正确渲染。
这是一张照片: Rendered Table
如您所见,第 1 行呈现正确。但是在重新渲染的第 2 行中,tds 被反转了。
这是我的代码:
var renderings = new Vue({
el: '#renderings',
data: function () {
return {
hasUnprocessedRenderings: false,
renderings: {}
};
},
methods: {
clearData: function () {
this.renderings = {};
},
updateData: function () {
this.$http.get('http://some-url.com/renderings').then(function (response) {
this.renderings = response.body.renderings;
this.hasUnprocessedRenderings = response.body.hasUnprocessedRenderings;
if (this.hasUnprocessedRenderings) {
setTimeout(this.updateData, 10000);
}
});
}
},
mounted: function() {
this.updateData();
}
});
和我的 html:
<div id="renderings">
<table class="table table-striped table-hover table-bordered" style="margin bottom: 0;">
<thead>
<tr>
<th>Personalisierung</th>
<th>Format</th>
<th>Download</th>
<th></th>
</tr>
</thead>
<tbody>
<template v-for="rendering in renderings">
<tr>
<td>{{rendering.personalizationName}}</td>
<td>{{rendering.renderTypeName}}</td>
<template v-if="rendering.DOCUMENT_URL">
<td><a :href="rendering.DOCUMENT_URL">{{rendering.DOCUMENT_URL}}</a></td>
<td>
<ul class="list-inline" style="margin-bottom: 0;">
<li><a :href="'http://some-url.com?pid='+rendering.PROCESS_ID" title="refresh"><i class="fa fa-refresh" aria-hidden="true"></i></a></li>
<li><a :href="'http://some-url.com?pid='+rendering.PROCESS_ID" title="delete"><i class="fa fa-trash-o" aria-hidden="true"></i></a></li>
</ul>
</td>
</template>
<template v-else>
<td colspan="2" style="text-align: center;">
<i class="fa fa-cog fa-spin fa-fw"></i>
<span>In Bearbeitung..</span>
</td>
</template>
</tr>
</template>
</tbody>
</table>
</div>
所以我的问题是:如何修复该行是否正确重新呈现?
感谢您的帮助。 :-)
编辑#1: 这是一个 jsfiddle,问题也出现在这里:https://jsfiddle.net/dt1kt06g/
似乎这种行为是 Vue 虚拟 DOM 算法优化的副作用。发生更新时,Vue 会尽量减少元素移动,而是重用和修补现有的 DOM 个节点。
当您在数据更新后检查 JSFiddle 中生成的 HTML 时,您会注意到第二个 <tr>
中的最后一个 <td>
仍然具有属性 colspan="2" style="text-align: center;"
,这给了我们一个提示,这个 <td>
元素被错误地从 v-else
中先前呈现的 "In Progress" 单元格中重用了。 (我不确定这是否可以被描述为 Vue 中的错误...)
无论如何,这个问题有一个解决方法:Vue 有一个特殊的 key
属性,它为节点差异算法提供了如何处理元素的提示 (see documentation)。在您的示例中,向 v-else
分支中的 <td>
添加一个密钥就足够了:
<template v-else>
<td colspan="2" style="text-align: center;" :key="rendering.PROCESS_ID">
...
这是您的 JSFiddle 的 fixed version。
问题可能与您使用 this.renderings = {...}
要分配对象属性,您应该为每个新值使用 Vue.set(this.renderings, key, value)
,或者 this.renderings = Object.assign({}, this.renderings, newData)
根据您使用的数据的嵌套程度,这可能完美或不完美,您可以在此处找到有关它的更多信息:https://vuejs.org/v2/guide/reactivity.html