VueJS:`v-for`不渲染元素
问题:VueJS:v-for不渲染元素 尽管我想分享只是以简化版本分享相关代码,但我不能。我有一个用 Vue 制作的稍微过度的 todo 应用程序。这是回购的链接:https://github.com/jaiko86/subtasks 待办事项在商店中管理: export default { state: { workspaceIds: [], // IDs of workspaces tasks
问题:VueJS:v-for
不渲染元素
尽管我想分享只是以简化版本分享相关代码,但我不能。我有一个用 Vue 制作的稍微过度的 todo 应用程序。这是回购的链接: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;
}
},
},
基本上,计算属性只会返回与某些条件相关的任务列表,例如我所在的工作区。每个任务都有一个唯一的 ID,但为了调试,我已经这样做了每个任务都有task-
格式的 ID,任务的输入将有它的任务 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 和控制台中显示的内容与视图之间存在差异时失败了。
这是渲染的视图:
这是 vue 开发工具中的内容:
这是我在开发工具中选择<App>
组件时控制台中打印的内容,从而可以通过访问它:
["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 都会返回一个包含两个项目的列表,但它只呈现第一个项目。
解答
这是一种可能的解释...
在计算属性返回其数组时,该数组仅包含一项。您可以通过多种方式确认这一点。例如尝试将其放入您的模板中:
{{ taskIds }}
该数组随后可能会更改,使其包含两个项目,但如果更改未触发反应系统,则不会发生重新渲染。
最好的猜测是tasksIds
正在返回tasksById[currentWorkspaceId].subTaskIds
。这留下了两种可能的可能性。subTasksIds
不是反应性的,或者它正在以不触发反应性的方式进行修改(例如,通过索引直接修改)。
查看您的商店代码,我看不到后者的任何明显示例。但是,这条线来自createTask
确实看起来像前者一样可疑:
state.tasksById[task.id] = task;
这是将task
添加到(可能)新键下的现有对象中。这是反应性警告之一,您不能直接向对象添加新属性:
https://v2.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
,将在控制台中显示为普通对象/数组。值得花一些时间来了解其中的差异,因为如果您知道要查找什么,它会使调试这些类型的问题变得更加容易。
更多推荐
所有评论(0)