在Vue js中使用v-for
循环。我正在遍历readingTasks
数据对象,该对象从下面的数据正确地产生了两个结果。
readingTasks:Array[2]
0:Object
enabled:true
newunit:-1
task:"The part 3 guide"
unit:-1
unit_task_id:27
url:"#"
1:Object
enabled:true
newunit:-1
task:"The part 3 training units"
unit:-1
unit_task_id:28
url:"#"
我不确定的是如何获得每个结果,如何运行另一个Axios
数据库调用,该调用显示读取任务是否完成。例如,对于第一条记录,完整状态应为true(unit_task_id:27),而第二条记录应为false。
userTasks:Array[1]
0:Object
complete:true
enabled:true
newunit:-1
task:"The part 3 guide"
unit:-1
unit_task_id:27
unit_task_user_id:21
<ul>
<li v-for="task in readingTasks">
{{task.task}}
//trying to call a function that does an Axios call passing in parameters from readingTasks
{{getUserTaskByUnit(task.unit, task.unit_task_id)}}
<template v-for="usertask in userTasks">
{{usertask.complete}}
</template>
</li>
</ul>
//javascript if its useful
data: {
readingTasks: [],
userTasks: []
},
mounted() {
this.lastUnit();
},
methods: {
//functons
lastUnit: function() {
this.tasks();
},
tasks: function() {
var self = this;
var unit = this.unit;
axios.get("/WebService/units.asmx/GetTasks?unit=" + unit).then(function(response) {
self.readingTasks = response.data;
})
.catch(function(error) {
console.log(error);
})
.then(function() {
});
},
getUserTaskByUnit: function(unit, unitTaskId) {
var self = this;
axios.get("/WebService/units.asmx/GetUserTasks?unit=" + unit + "&unitTaskId=" + unitTaskId).then(function(response) {
self.userTasks = response.data;
})
.catch(function(error) {
console.log(error);
})
.then(function() {});
}
该代码似乎在做正确的事情,但是对于两组结果,{{usertask.complete}}
在true和false之间闪烁。就像卡在一个循环中一样。
我希望第一个结果在这里显示True,第二个结果显示False。
第3部分指南-true
第3部分训练单元-错误
答案 0 :(得分:0)
您的userTasks
是一个视图属性,在每次调用getUserTaskByUnit
时都会被覆盖(即readingTasks
中的每个项目)。相反,您需要的是一个嵌套结构。您应在getUserTaskByUnit
加载后立即在循环中调用readingTasks
,即在self.readingTasks = response.data;
行之后,并将响应存储为每个readingTask
对象的属性。>
答案 1 :(得分:0)
这里有一些问题。
模板依赖于userTasks
,因此每次userTasks
进行更改都会导致组件重新渲染,从而再次运行模板。
每次模板运行时,它都会为两个任务调用getUserTaskByUnit
。这将异步更新userTasks
。 userTasks
更新后,将触发重新渲染,该渲染将再次调用getUserTaskByUnit
,并在无限循环中循环。
更糟糕的是,这不仅是一个无限循环,每次渲染都会触发两个请求,每个请求都会触发另一个重新渲染。请求数量将成倍增加。
当这些请求返回时,您会将它们存储在userTasks
中。但是,这两个响应都存储在完全相同的位置,因此您只会在UI中看到一个请求的结果。
您首先需要的是一个更好的数据结构,用于将响应存储在getUserTaskByUnit
中。存储它们的最简单位置是在readingTask
中的任务上。可能看起来像这样:
// Note the whole task is now being passed to getUserTaskByUnit
getUserTaskByUnit: function(task) {
var self = this;
axios.get("/WebService/units.asmx/GetUserTasks?unit=" + task.unit + "&unitTaskId=" + task.unit_task_id).then(function(response) {
task.userTasks = response.data;
})
...
}
对getUserTaskByUnit
的调用需要移出模板。将其移至tasks
方法似乎是一个好地方。要使其与新版本的getUserTaskByUnit
一起使用,还需要进行一些更改:
tasks: function() {
var self = this;
var unit = this.unit;
axios.get("/WebService/units.asmx/GetTasks?unit=" + unit).then(function(response) {
var readingTasks = response.data;
// Pre-populate userTasks so it will be reactive
readingTasks.forEach(function(task) {
task.userTasks = [];
});
// This must come after userTasks is pre-populated
self.readingTasks = readingTasks;
readingTasks.forEach(function(task) {
// Passing task to getUserTaskByUnit, not unit and unit_task_id
self.getUserTaskByUnit(task);
});
})
...
然后在模板中,我们需要遍历task.userTasks
:
<ul>
<li v-for="task in readingTasks">
{{task.task}}
<template v-for="usertask in task.userTasks">
{{usertask.complete}}
</template>
</li>
</ul>
根据您的其他要求,我们可以使用其他数据结构。例如,您可以保留一个单独的userTasks
对象来容纳userTasks
,但是要使其正常工作,它必须是嵌套的数据结构,而不仅仅是数组。您需要先按unit
键,然后按unitTaskId
键。模板中的结果将如下所示:
<ul>
<li v-for="task in readingTasks">
{{task.task}}
<template v-for="usertask in userTasks[task.unit][task.unit_task_id]">
{{usertask.complete}}
</template>
</li>
</ul>
与早期解决方案非常相似,您需要在userTasks
首次加载时用空值预填充readingTasks
,以确保这些值是反应性的,并且还可以避免模板在{ {1}}个条目。另外,您可以分别使用undefined
和合适的$set
检查。
这一切都很奇特。可能您可以根据对系统的了解来对其进行一些简化。例如,可以为v-if
形成复合字符串键,而不是使用两个嵌套级别。也许userTasks
是可以被认为是常量的道具,不需要包含在该数据结构中。