【发布时间】:2021-11-13 22:51:51
【问题描述】:
问题
我正在使用 Vue 构建一个项目,其中有一个项目列表,每个项目都有一个打开和删除按钮。现在我需要使用单独的组件为每个项目添加标签。我想为每个列表项单独切换此组件的呈现,以创建一个包含可折叠项的列表。
我的第一次尝试看起来像这样:
<b-list-group v-if="!isLoading">
<b-list-group-item v-for="project in projects" :key="project.path">
{{ project.name }}
<b-btn variant="danger" size="sm" class="list-button" @click="deleteProject(project.path)">Löschen</b-btn>
<b-btn variant="secondary" size="sm" class="list-button" @click="openProject(project.path)">Öffnen</b-btn>
<b-btn variant="secondary" size="sm" class="list-button" @click="project.showTags = !project.showTags">Tags</b-btn>
<search-tags v-if="project.showTags" style="margin-top: 1em;"></search-tags>
</b-list-group-item>
如果我控制台记录我的this.projects,我可以看到每个项目的值都正确更改。尽管如此,即使project.showTags == true,v-if 也不会呈现。
然后我读到,你不应该在 v-for 中使用 v-if,所以我尝试了 Bootstrap-Vue collapse 组件:
<b-list-group v-if="!isLoading">
<b-list-group-item v-for="project in projects" :key="project.path">
{{ project.name }}
<b-btn variant="danger" size="sm" class="list-button" @click="deleteProject(project.path)">Löschen</b-btn>
<b-btn variant="secondary" size="sm" class="list-button" @click="openProject(project.path)">Öffnen</b-btn>
<b-btn variant="secondary" size="sm" class="list-button" @click="project.showTags = !project.showTags">Tags</b-btn>
<b-collapse v-model="project.showTags">
<search-tags style="margin-top: 1em;"></search-tags>
</b-collapse>
</b-list-group-item>
但这也不起作用。
我认为这不会那么困难,我在这里遗漏了一些东西。任何帮助表示赞赏。
编辑 1
从我的代码中可以看出,整个列表都放在<b-list-group> 中,它根据isLoading 有条件地呈现。如果我通过翻转isLoading 强制重新加载,然后翻转project.showTags,然后将isLoading 翻转回来,它可以工作。但我觉得这个解决方案超级阴暗和hacky。
工作但丑陋的代码:
<b-list-group-item v-for="project in projects" :key="project.path">
{{ project.name }}
<b-btn variant="danger" size="sm" class="list-button" @click="deleteProject(project.path)">Löschen</b-btn>
<b-btn variant="secondary" size="sm" class="list-button" @click="openProject(project.path)">Öffnen</b-btn>
<b-btn variant="secondary" size="sm" class="list-button" @click="test(project)">Tags</b-btn>
<search-tags v-show="project.showTags" style="margin-top: 1em;"></search-tags>
</b-list-group-item>
</b-list-group>
与:
test(project) {
this.isLoading = !this.isLoading;
project.showTags = !project.showTags;
console.log(this.projects);
this.isLoading = !this.isLoading;
},
编辑 2
我的数据首先是这样定义的:
data() {
return {
projects: [],
tags: [],
newProject: false,
isLoading: true,
isError: false,
form: {
name: '',
},
};
},
然后在created() 我打电话给getAllProjects() 从后端获取我的项目:
created() {
this.getAllProjects();
},
我的项目没有 showTags 属性,所以我在获取后直接分配它:
async getAllProjects() {
try {
this.isLoading = true;
const res = await fetch(store.state.urlEndpoints.getProjects, {
...AuthPost(), // request config object
});
this.projects = JSON.parse(await res.text());
this.projects.forEach((project) => { project.showTags = false; });
console.log(this.projects);
this.isLoading = false;
} catch (err) {
this.isError = true;
this.isLoading = false;
}
},
我在每次单击“标签”按钮时 console.log this.projects,如上面 test() 函数中所示。值会按照我的意图翻转。
【问题讨论】:
-
projects是如何定义的?当您为其赋值时,每个项目 (project) 是否具有showTags属性(true或false)? -
@Phil 是的,没错。
projects是一个对象数组,每个project都有一个属性showTags初始化为false并被@click翻转。projects数组的行为与我想要的完全一样,v-for 循环内的元素只是没有响应更改。如您所见,整个内容都包裹在b-list-group中,它也是有条件地呈现的。如果我通过两次翻转isLoading来强制重新呈现列表,则一切正常。但我觉得这是一个超级靠不住的解决方案。 -
我的第一个想法是反应不够深:参考这个链接:vuejs.org/v2/guide/reactivity.html#For-Objects
-
您的数据是如何定义的?你能用
v-if="projects.length > 0"做吗?
标签: javascript html vue.js frontend