javascript - 我应该如何动态更新firebase文档
问题描述
我正在使用 JS 和 Firebase 为我的投资组合开发一个简单的笔记应用程序。在我告诉你发生了什么之前,我觉得我需要向你展示我的代码是如何工作的,如果你有任何提示和疑虑,请告诉我,我们将不胜感激。话虽如此,让我们“一起”看看。我正在使用这个类来创建笔记:
const htmlElements = [document.querySelector('.notes'), document.querySelector('.note')];
const [notesDiv, noteDiv] = htmlElements;
class CreateNote {
constructor(title, body) {
this.title = title;
this.body = body;
this.render = () => {
const div1 = document.createElement('div');
div1.className = 'notes-prev-container';
div1.addEventListener('click', () => { this.clickHandler(this) });
const div2 = document.createElement('div');
div2.className = 'notes-prev';
const hr = document.createElement('hr');
hr.className = 'notes__line';
// Nest 'div2' inside 'div1'
div1.appendChild(div2);
div1.appendChild(hr);
/*
Create Paragraph 1 & 2 and give them the same
class name and some text
*/
const p1 = document.createElement('p');
p1.className = 'notes-prev__title';
p1.innerText = this.title;
const p2 = document.createElement('p');
p2.className = 'notes-prev__body';
p2.innerText = this.body;
// Nest p 1 & 2 inside 'div2'
div2.appendChild(p1);
div2.appendChild(p2);
// Finally, render the div to its root tag
notesDiv.appendChild(div1);
}
}
/*
Every time this method is called, it creates 2 textareas,
one for the note title and the other for its body then it
appends it to the DOM.
*/
renderNoteContent () {
const title = document.createElement('textarea');
title.placeholder = 'Title';
title.value = this.title;
title.className = 'note__title';
const body = document.createElement('textarea');
body.placeholder = 'Body';
body.value = this.body;
body.className = 'note__body';
noteDiv.appendChild(title);
noteDiv.appendChild(body);
}
/*
When this method is called, it checks to see if there's a
note rendered already (childElementCount === 1 because there's a
button, so if there's only this button it means there's no
textareas rendered).
If yes, then merely call the renderNoteContent method. Else
get the tags with the classes 'note__title' and 'note__body'
and remove them from the DOM, then call renderNoteContent to
create the textareas with the clicked notes values.
This function gets mentioned at line 19.
*/
clickHandler(thisClass) {
if (noteDiv.childElementCount === 1) {
thisClass.renderNoteContent();
} else {
document.querySelector('.note__title').remove();
document.querySelector('.note__body').remove();
thisClass.renderNoteContent();
}
}
}
现在我需要2个按钮,createNotesButton
分别saveNotesButton
。这 2 个按钮必须位于将在内部调用的函数内.onAuthStateChanged
(为什么?因为它们需要访问currentUser
on firebase 身份验证)。
我想createNotesButton
创建一个便笺原型,将其渲染到 DOM 并在 firestore 上创建一个新文档,该便笺内容将存储在其中。我是这样做的:
PS:我觉得我没有正确使用这个类,所以如果你有任何提示,我很感激。
import {db} from '../../firebase_variables/firebase-variables.js';
import {CreateNote} from '../create_notes_class/create_notes_class.js';
const htmlElements = [
document.querySelector('.createNotes-button'),
document.querySelector('.saveNotes-button')
];
const [createNotesButton, saveNotesButton] = htmlElements;
function clickHandler(user) {
/*
1. Creates a class.
2. Creates a new document on firebase with the class's empty value.
3. Renders the empty class to the DOM.
*/
createNotesButton.addEventListener('click', () => {
const note = new CreateNote('', '');
note.render();
// Each user has it's own note collection, said collection has their `uid` as name.
db.collection(`${user.uid}`).doc().set({
title: `${note.title}`,
body: `${note.body}`
})
})
}
现在我需要一个saveNotesButton
,他是我遇到问题的人。他需要将显示的便笺内容保存在 Firestore 上。这是我尝试做的事情:
import {db} from '../../firebase_variables/firebase-variables.js';
import {CreateNote} from '../create_notes_class/create_notes_class.js';
const htmlElements = [
document.querySelector('.createNotes-button'),
document.querySelector('.saveNotes-button')
];
const [createNotesButton, saveNotesButton] = htmlElements;
function clickHandler(user) {
createNotesButton.addEventListener('click', () => {...})
/*
1. Creates 2 variables, `title` and `body, if there's not a note being displayed
their values will be null, which is why the rest of the code is inside an if
statement
2. If statement to check if there's a note being displayed, if yes then:
1. Call the user's note collection. Any document who has the title field equal to the
displayed note's value gets returned as a promise.
2. Then call an specific user document and update the fields `title` and `body` with
the displayed note's values.
3. If no then do nothing.
*/
saveNotesButton.addEventListener('click', () => {
const title = document.querySelector('.note__title');
const body = document.querySelector('.note__body');
db.collection(`${user.uid}`).where('title', '==', `${title.value}`)
.get()
.then(userCollection => {
db.collection(`${user.uid}`).doc(`${userCollection.docs[0].id}`).update({
title: `${title.value}`,
body: `${body.value}`
})
})
.catch(error => {
console.log('Error getting documents: ', error);
});
});
}
这不起作用,因为我将title.value
其用作查询,因此如果我更改它的值,它也会将查询方向更改为不存在的路径。
那么问题来了:我怎样才能让 saveNotesButton 完成它的工作?我正在考虑为每个便笺添加另一个字段,该字段不会更改,因此我可以轻松识别和编辑每个便笺。同样,如果您认为我的代码中的某些内容可以或应该被格式化,请告诉我,我正在使用这个项目来巩固我的原生 JS 知识,所以请耐心等待。我觉得如果我使用过 React,我会在一段时间前完成这个,但肯定不会学到很多东西,无论如何提前感谢您的帮助。
解决方案
我正在考虑为每个便笺添加另一个字段,该字段不会更改,因此我可以轻松识别和编辑每个便笺。
是的,对于 firestore 中的每个便笺文档,您绝对需要一个不可变的标识符,以便您可以明确地引用它。每当您在具有任何数据库的任何应用程序中存储数据对象时,您几乎总是需要这个。
但是,firestore 已经为您执行了此操作:调用后,db.collection(user.uid).doc()
您应该得到一个带有 ID的文档。这是您在更新笔记时要使用的 ID。
与 DOM 交互的代码部分需要跟踪这一点。我建议将创建 firestore 文档的代码移动到构造函数中CreateNote
并将其存储在this
. 您还需要那里的用户 ID。
constructor(title, body, userId) {
this.title = title;
this.body = body;
const docRef = db.collection(userId).doc();
this.docId = docRef.id;
/* etc. */
然后,只要您有 的实例CreateNote
,您就会知道要引用的正确用户和文档。
其他建议(因为你问过)
- 使用 JsPrettier。这是值得的设置,你永远不会回去。
- 正确使用 HTML 语义。Div 不应该作为 hrs 的子级附加,因为它们用于“段落级元素之间的主题中断:例如,故事中的场景变化,或章节内的主题转移”。MDN
- 对于您的下一个项目,请使用框架。基本上没有人手动编码事件监听器并附加孩子来完成事情。我看到了基本理解的价值,但是那里有一个丰富而美丽的框架世界;不要通过避免它们来限制自己:-)
推荐阅读
- javascript - 从包含空格的字符串中获取路径
- tomcat - IntelliJ 的运行配置中的 Tomcat 配置
- javascript - 在执行“yarn/npm publish”时忽略“nsp check”?
- elasticsearch - 如何使用 elasticsearch-py 追加到 Elasticsearch 中的数组
- vba - VBA获取最后一个发票号并保存新发票
- excel - 如何使用 Match 函数并引用它返回的行号?
- amcharts - 以编程方式在钻取地图 amchart 中放置标记
- python - 使用用户 id Django 保存表单
- python - 在 windows 命令提示符下使用 python
- ios - 当应用程序准备好呈现警报时,从 AppDelegate 呈现警报