繁体   English   中英

我应该如何动态更新 firebase 文档

[英]how should i dynamically update a firebase document

我正在使用 JS 和 Firebase 为我的投资组合开发一个简单的笔记应用程序。在我告诉你发生了什么之前,我觉得我需要向你展示我的代码是如何工作的,如果你有任何提示和疑虑,请告诉我它将不胜感激。 话虽如此,让我们“一起”看看。 我正在使用这个 class 来创建笔记:

 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 个按钮,分别是createNotesButtonsaveNotesButton 这 2 个按钮必须位于 function 内,将在.onAuthStateChanged内调用(为什么?因为它们需要访问 firebase 身份验证上的currentUser )。

我希望createNotesButton创建一个笔记原型,将其渲染到 DOM 并在 firestore 上创建一个新文档,该文档内容将存储在该文档中。 我是这样做的:

PS:我觉得我没有正确使用这个 class,所以如果你有任何提示,我再次感谢。

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 中的每个笔记文档提供一个不可变的标识符,以便您可以明确地引用它。 每当您在具有任何数据库的任何应用程序中存储数据 object 时,您几乎总是需要这个。

但是,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。 这是值得的设置,你永远不会 go 回来。
  • 正确使用 HTML 语义。 Div 不应作为 hrs 的子元素附加,因为它们用于“段落级元素之间的主题中断:例如,故事中场景的变化,或部分中主题的转变”。MDN
  • 对于您的下一个项目,请使用框架。 基本上没有人手动编写事件侦听器代码并附加子项来完成工作。 我看到了基本理解的价值,但是那里有一个丰富而美丽的框架世界; 不要通过避免它们来限制自己:-)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM