VueJS:“ v-for”不呈现元素

时间:2019-08-12 17:18:44

标签: javascript vue.js vuejs2

我想分享的只是共享简化版本中的相关代码,我不能。我有一个用Vue制作的稍微超标的待办事项应用程序。这是仓库的链接:https://github.com/jaiko86/subtasks

待办事项在商店中管理:

export default {
  state: {
    workspaceIds: [], // IDs of workspaces
    tasksById: {}, // <--- this is the tasks I have
    detachedTask: null,
    focusedTaskId: null,
    currentWorkspaceId: null,
  },
  ...
}

在App.vue文件中,我具有以下v-for将运行的计算属性:

  computed: {
    taskIds() {
      const { currentWorkspaceId, tasksById } = this.$store.state;
      if (this.showOnlyLeafSubTasks) {
        return Object.values(tasksById)
          .filter(task => !task.subTaskIds.length)
          .map(task => task.id);
      } else if (currentWorkspaceId) {
        return tasksById[currentWorkspaceId].subTaskIds;
      }
    },
  },

基本上,calculated属性将仅返回与某些条件相关的任务列表,例如我所在的工作区。每个任务都有唯一的ID,但是为了进行调试,我做了它使每个任务的ID的格式为task-#,并且该任务的输入将其任务ID作为占位符。

这是App.vue中的模板:

<template>
  <div id="app">
    <!-- This is the top part -->
    <WorkspaceNav /> 

    <!-- this is the for-loop in question -->
    <TaskWrapper v-for="id in taskIds" :key="id" :id="id" :depth="0" />

    <!-- this is the filter that's on the right side -->
    <TaskFilters />
  </div>
</template>

问题在于它不会呈现计算属性返回的项目。

在尝试理解为什么在vue devtool和控制台中显示的内容与视图之间为什么存在差异时,我很痛苦。

这是渲染的视图: The rendered view

以下是vue开发工具中的内容: Vue devtool showing state of App.vue

这是我在开发工具中选择<App>组件时在控制台上打印的内容,从而可以通过$vm0.taskIds进行访问:

["task-1", "task-2"]

这是我的自定义函数,可按层次打印任务:

> printTree()
task-0
  task-1

  task-2

这是当前代码相关部分的DOM:


    <div id="app">
      <div class="workspace-nav">
        ...
      </div>
      <div data-v-76850a4a="" data-v-7ba5bd90="" class="leaf">
        <div data-v-76850a4a="" class="main-task depth-0">
          <!---->
          <div class="progress-indicator">
            <div class="checkmark gray-checkmark"></div>
          </div>
          <input placeholder="task-1" />
        </div>
        <div class="sub-tasks"></div>
      </div>
      <div class="filters">
        ...
      </div>
    </div>

很明显,无论我在哪里看,taskIds都将返回两个项目的列表,但是它仅呈现第一个项目。

1 个答案:

答案 0 :(得分:1)

这是一种可能的解释...

在计算属性返回其数组时,该数组仅包含一项。您可以通过几种方式确认这一点。例如尝试将其放在模板中:

{{ taskIds }}

随后可以更改该数组,使其包含两个项目,但是如果更改未触发反应性系统,则不会重新渲染它们。

最好的猜测是tasksIds返回tasksById[currentWorkspaceId].subTaskIds。这留下了两种可能的可能性。 subTasksIds没有反应性,或者正在以不会触发反应性的方式对其进行修改(例如,按索引直接修改)。

看看您的商店代码,我看不到后者的任何明显示例。但是,createTask中的this line似乎与前者类似:

state.tasksById[task.id] = task;

这是在(可能是)新键下将task添加到现有对象。这是反应性警告之一,您不能直接向对象添加新属性:

https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats

相反,您需要使用Vue.set

Vue.set(state.tasksById, task.id, task);

为更好地了解发生了什么,请尝试在createTask的末尾添加以下日志:

console.log(state.tasksById);

如果您在控制台中深入研究对象/数组,则应该看到Vue反应系统的证据。您可能会看到对Observer的引用。属性将具有getter和setter,并且您需要单击以查看属性值。但是,这仅在对象/数组是反应性的时才会发生。您直接添加而没有Vue.set的任务将在控制台中仅显示为普通对象/数组。值得花一些时间来了解差异,因为如果您知道要查找的内容,它将使调试这类问题变得更加容易。