对于v-for循环中的每个结果,如何使用第一个循环的结果中的参数嵌套另一个v-for循环

时间:2019-09-03 09:31:39

标签: vue.js vuejs2 axios

在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部分训练单元-错误

2 个答案:

答案 0 :(得分:0)

您的userTasks是一个视图属性,在每次调用getUserTaskByUnit时都会被覆盖(即readingTasks中的每个项目)。相反,您需要的是一个嵌套结构。您应在getUserTaskByUnit加载后立即在循环中调用readingTasks,即在self.readingTasks = response.data;行之后,并将响应存储为每个readingTask对象的属性。

答案 1 :(得分:0)

这里有一些问题。

模板依赖于userTasks,因此每次userTasks进行更改都会导致组件重新渲染,从而再次运行模板。

每次模板运行时,它都会为两个任务调用getUserTaskByUnit。这将异步更新userTasksuserTasks更新后,将触发重新渲染,该渲染将再次调用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是可以被认为是常量的道具,不需要包含在该数据结构中。