javascript - 从列表中添加/删除项目后使用 onSnapshot 正确呈现任务列表
问题描述
我在做什么
我正在使用 vue 和 firestore 制作一个简单的任务组织应用程序。到目前为止,我做了 5 个功能。
- 登录
- 报名
- 获取并渲染任务列表
- 添加/删除任务
- [不工作!] 实时渲染任务列表中的任何更改
无法正常工作
它从 firestore 获取并加载数组数据并实时渲染,但无法正确渲染
问题详情
由于在列表中添加或删除任务而更新列表时,此问题变得可见。
请检查图像以获得更清晰的问题图像。
我试过的
- 通过刷新页面来解决,但失去了实时更新的意义。
- 在某处看到 set Vue() / new Vue() 会解决,但没有。(或者更像是我太初学者,无法理解这个概念来应用它......)
很可能我不理解背后的真正问题是什么......所以如果有人能指出我真正的问题是什么,那就太好了。所以期待听到你的想法!
代码
主要有两个文件负责渲染任务列表。
- projectList.vue :我在其中获取和加载数组数据并呈现任务列表
- projectCard.vue :我为 projectList.vue 插入每个任务的数据以创建列表。
(我还将添加用于添加项目的脚本;addProject.js 以防万一。)
projectList.vue :获取、加载、渲染任务列表
<template>
<div class="projectList">
<button class="home-buttons" @click="newProject">Add project</button>
<div v-if="createNew">
<projectAdd/>
</div>
<div v-show="loading">
<Loader/>
</div>
<div v-show="!loading">
<!--03 Pass array data to projectCard.vue then render the list of entries-->
<projectCard v-for="project in projects" :key="project.id" :project="project"/>
</div>
<p v-show="noproject">There is no project</p>
</div>
</template>
<script>
import firebase from '@/firebase/firestore';
import Loader from '@/components/loading.vue';
import projectCard from '@/components/projectCard.vue';
import projectAdd from '@/components/addProject.vue';
export default {
components: {
projectCard,
Loader,
projectAdd,
},
data() {
return {
userid: this.$route.params.userId,
//02 Put array data here
projects: [],
loading: true,
createNew: false,
};
},
created() {
//01 Get datas in realtime then pass an array data to projects: []
const db = firebase.firestore()
.collection('user')
.doc(this.userid) //$route.params.userId
.collection('projects')
.orderBy('createdAt', 'desc');
db
.onSnapshot((querySnapshot) => {
querySnapshot.forEach((doc) => {
this.projects.push(doc.data());
});
if (this.projects.length >= 0) {
this.loading = false;
} else if (this.projects.length <= 0) {
this.loading = false;
}
});
},
methods: {
newProject() {
if (this.createNew !== true) {
this.createNew = true;
} else {
this.createNew = false;
}
},
},
};
</script>
projectCard.vue :将每个数据插入数组
<template>
<div class="projectCard">
<div class="user-list">
<div class="columns">
<div class="column is-8">
<h3>{{ project.projectname }}</h3>
<p>{{ project.slug }}</p>
<p>Why : {{ project.why }}</p>
<p>{{ project.phase }}</p>
</div>
<div class="column is-4 right">
<router-link class="button is-primary" :to="{ name: 'viewproject', params: { projectId: project.slug }}">
Find out more!
</router-link>
<button @click="deleteProject"> Delete </button>
</div>
</div>
</div>
</div>
</template>
<script>
import firebase from '@/firebase/firestore';
export default {
name: 'ProjectCard',
props: {
// Holds array data from parent-component; projectList.vue
project: Object,
},
methods: {
// Delete a task
deleteProject() {
firebase.firestore().collection('user').doc(this.project.userId)
.collection('projects')
.where('slug', '==', this.project.slug)
.get()
.then((snapshot) => {
snapshot.forEach((doc => {
console.log(doc.data().slug);
doc.ref.delete();
alert('You have deleted the project!' + doc.data().slug);
}))
})
},
},
};
</script>
addProject.js :添加任务(此功能可从 projectList.vue 中呈现的另一个组件访问)
import firebase from '@/firebase/firestore';
export default {
addProject(createdAt, userId,projectname,why,phase){
const db = firebase.firestore().collection("user")
.doc(userId).collection("projects"); // "Project"という名前のコレクションへの参照を作成
db.add({
createdAt: createdAt,
userId: userId,
projectname: projectname,
why: why,
phase: phase,
slug: this.generateUUID(),
})
.then(function (docRef) {
console.log('Document written with ID: ', docRef.id);
alert('Well done! You have created a new project!');
})
.catch(function (error) {
console.error('Error adding document: ', error);
});
},
generateUUID() {
let d = new Date().getTime();
let uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
let r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
return uuid;
},
};
感谢您花费宝贵的时间阅读本文并帮助我解决这个问题!期待听到你们的一些想法!
解决方案
这是因为每次触发侦听器时,您都会收到查询的全部结果,即与其对应的所有文档。
你基本上有两个选择:
选项 1:重新初始化您的阵列
在填充之前重新初始化您的数组,如下所示:
created() {
const db = firebase.firestore()
.collection('user')
.doc(this.userid) //$route.params.userId
.collection('projects')
.orderBy('createdAt', 'desc');
this.projects = []; <-- See here
db
.onSnapshot((querySnapshot) => {
querySnapshot.forEach((doc) => {
this.projects.push(doc.data());
});
if (this.projects.length >= 0) {
this.loading = false;
} else if (this.projects.length <= 0) {
this.loading = false;
}
});
},
选项 2:聆听实际变化
如文档中所述,您可以检测“查询快照之间查询结果的实际变化”。
例如,您只能处理添加,如下所示:
db
.onSnapshot((querySnapshot) => {
querySnapshot.docChanges().forEach((change) => {
if (change.type === "added") {
this.projects.push(change.doc.data());
}
//....
});
//....
});
推荐阅读
- node.js - express.Router 在自己的文件中分离时命中 404 而不是路由
- javascript - 输出为字符串
- javascript - 将 textInput 元素移动到单独的组件
- haskell - 如何在haskell中解析字符串?
- laravel - 每个客户而不是用户的客户 ID 和密钥
- python-3.x - 在网站 Django 上实现谷歌分析
- python - Pandas:通过从列表的字典映射创建一列
- imagemagick - imagemagick 裁剪图像创建锯齿状边缘或锯齿形状
- swift - 快捷方式项目 - 执行 Segue
- python - 使用 django 获取表格形式的 json 对象中的字段中的值