了解網頁版 Firebase

在本程式碼實驗室中,您將學習一些基礎知識的火力地堡創建交互式Web應用程序。您將使用多個 Firebase 產品構建一個活動 RSVP 和留言簿聊天應用。

59abdefbcc23bbbe.png

你會學到什麼

  • 使用 Firebase 身份驗證和 FirebaseUI 對用戶進行身份驗證。
  • 使用 Cloud Firestore 同步數據。
  • 編寫 Firebase 安全規則來保護數據庫。

你需要什麼

  • 您選擇的瀏覽器,例如 Chrome。
  • 訪問stackblitz.com (不考慮或登錄必要)。
  • Google 帳戶,例如 Gmail 帳戶。我們推薦您已用於 GitHub 帳戶的電子郵件帳戶。這允許您使用 StackBlitz 中的高級功能。
  • Codelab 的示例代碼。有關如何獲取代碼,請參閱下一步。

在本程式碼實驗室,您使用的是建立一個應用程序StackBlitz ,有幾個火力地堡工作流程集成到它的在線編輯器。 Stackblitz 不需要安裝軟件或特殊的 StackBlitz 帳戶。

StackBlitz 可讓您與他人共享項目。其他擁有您的 StackBlitz 項目 URL 的人可以看到您的代碼並創建您的項目,但他們無法編輯您的 StackBlitz 項目。

  1. 去這個網址為起點代碼: https://stackblitz.com/edit/firebase-gtk-web-start
  2. 在StackBlitz頁面的頂部,點擊f5135360aef481cc.png

您現在擁有一份起始代碼的副本作為您自己的 StackBlitz 項目。因為你沒有登錄,您的帳戶被稱為@anonymous ,但該項目具有獨特的名稱,具有獨特的URL一起。您的所有文件和更改都保存在此 StackBlitz 項目中。

此 Codelab 的起始材料為 Web 應用程序提供了一些結構,包括一些樣式表和應用程序的幾個 HTML 容器。在本 Codelab 的稍後部分,您會將這些容器連接到 Firebase。

首先,讓我們更熟悉 StackBlitz 界面。

  1. 在StackBlitz,打開index.html文件。
  2. 找到event-details-containerdescription-container ,然後嘗試編輯一些事件的詳細信息。

當您編輯文本時,StackBlitz 中的自動頁面重新加載會顯示新的事件詳細信息。酷,是嗎?

<!-- ... -->

<div id="app">
  <img src="..." />

  <section id="event-details-container">
     <h1>Firebase Meetup</h1>

     <p><i class="material-icons">calendar_today</i> October 30</p>
     <p><i class="material-icons">location_city</i> San Francisco</p>

  </section>

  <hr>

  <section id="firebaseui-auth-container"></section>

  <section id="description-container">
     <h2>What we'll be doing</h2>
     <p>Join us for a day full of Firebase Workshops and Pizza!</p>
  </section>
</div>

<!-- ... -->

您的應用程序的預覽應如下所示:

應用預覽

908cc57ce3a5b5fe.png

顯示活動信息對您的客人來說非常有用,但僅顯示活動對任何人來說都不是很有用。讓我們為這個應用程序添加一些動態功能。為此,您需要將 Firebase 連接到您的應用。要開始使用 Firebase,您需要創建並設置 Firebase 項目。

創建 Firebase 項目

  1. 登錄火力地堡
  2. 在火力地堡控制台,點擊添加項目(或創建一個項目),然後命名你的火力地堡火力地堡項目的Web-程式碼實驗室
    a67c239f8cc7f4b5.png
  3. 單擊項目創建選項。如果出現提示,請接受 Firebase 條款。跳過設置 Google Analytics,因為您不會為此應用使用 Analytics。

要了解更多關於火力地堡項目,請參閱了解火力地堡項目

在控制台中啟用 Firebase 產品

您正在構建的應用使用了多種可用於網絡應用的 Firebase 產品:

  • 火力地堡認證火力UI,很容易讓你的用戶在你的應用程序簽名。
  • 雲公司的FireStore保存在雲中的結構化數據,並得到即時通知的數據發生變化時。
  • 火力地堡安全規則,以確保您的數據庫。

其中一些產品需要特殊配置或需要使用 Firebase 控制台啟用。

為 Firebase 身份驗證啟用電子郵件登錄

要允許用戶在登錄到Web應用程序,你會使用電子郵件/密碼登錄方法對本程式碼實驗室:

  1. 在火力地堡控制台,點擊左側面板中生成
  2. 點擊身份驗證,然後點擊登錄方法選項卡(或點擊這裡直接進入到登錄方法選項卡)。
  3. 點擊登錄在供應商列表中的電子郵件/密碼,設置啟用開關至ON位置,然後點擊保存
    4c88427cfd869bee.png

啟用 Cloud Firestore

Web應用程序使用雲公司的FireStore保存聊天消息和接收新的聊天消息。

啟用 Cloud Firestore:

  1. 在火力地堡控制台的Build部分,單擊數據庫的FireStore。
  2. 單擊創建數據庫
    3ce19fd6467e51c5.png
  3. 在測試模式選項選擇開始。閱讀有關安全規則的免責聲明。測試模式確保您可以在開發過程中自由寫入數據庫。單擊下一步
    56369cebb9300eb.png
  4. 選擇數據庫的位置(您可以只使用默認值)。但請注意,此位置以後無法更改。
    32f815f4648c3174.png
  5. 點擊完成

現在您已經創建了 Firebase 項目並啟用了一些服務,您需要告訴代碼您要使用 Firebase,以及要使用哪個 Firebase 項目。

添加 Firebase 庫

要讓您的應用使用 Firebase,您需要將 Firebase 庫添加到應用中。有多種方法可以做到這一點,因為在火力地堡的文檔中描述。例如,您可以從 Google 的 CDN 添加庫,或者您可以使用 npm 在本地安裝它們,如果您使用的是 Browserify,則將它們打包到您的應用程序中。

StackBlitz 提供自動捆綁,因此您可以使用 import 語句添加 Firebase 庫。您將使用這些庫的模塊化 (v9) 版本,這有助於通過稱為“搖樹”的過程減小網頁的整體大小。您可以了解更多關於SDK的模塊化的文檔

要構建此應用,您需要使用 Firebase 身份驗證、FirebaseUI 和 Cloud Firestore 庫。對於本程式碼實驗室,以下import語句都已經包括在頂部index.js文件,當我們走,我們將進口來自各火力地堡庫的詳細方法:

// Import stylesheets
import './style.css';

// Firebase App (the core Firebase SDK) is always required
import { initializeApp } from 'firebase/app';

// Add the Firebase products and methods that you want to use
import {} from 'firebase/auth';
import {} from 'firebase/firestore';

import * as firebaseui from 'firebaseui';

將 Firebase 網絡應用添加到項目

  1. 早在火力地堡控制台中,導航到項目的概述頁面點擊項目概況在上面留下。
  2. 在項目概覽頁面的中心,單擊網絡圖標b286f3d215e1f578.png創建一個新的 Firebase 網絡應用。
    c167e9526fad2825.png
  3. 註冊暱稱Web應用程序的應用程序。
  4. 對於本程式碼實驗室,不檢查旁邊還設置了火力地堡主機為這個應用程序的複選框。您現在將使用 StackBlitz 的預覽窗格。
  5. 點擊註冊應用
    c85ac8aa351e2560.png
  6. 副本火力地堡配置對象到剪貼板。
    ed1e598c6132f734.png
  7. 點擊繼續安慰

將 Firebase 配置對象添加到您的應用:

  1. 早在StackBlitz,轉到index.js文件。
  2. 找到Add Firebase project configuration object here註釋行,然後粘貼剛才的評論下方的配置片段。
  3. 添加initializeApp函數調用來設置火力地堡用你獨特的火力地堡的項目配置。
    // ...
    // Add Firebase project configuration object here
    const firebaseConfig = {
      apiKey: "random-unique-string",
      authDomain: "your-projectId.firebaseapp.com",
      databaseURL: "https://your-projectId.firebaseio.com",
      projectId: "your-projectId",
      storageBucket: "your-projectId.appspot.com",
      messagingSenderId: "random-unique-string",
      appId: "random-unique-string",
    };
    
    // Initialize Firebase
    initializeApp(firebaseConfig);
    

現在,您已經添加火力地堡的應用程序,你可以設置一個回复按鈕,使用註冊人火力地堡認證

使用電子郵件登錄和 FirebaseUI 對您的用戶進行身份驗證

您需要一個 RSVP 按鈕來提示用戶使用他們的電子郵件地址登錄。您可以通過掛鉤做到這一點FirebaseUI到RSVP button.FirebaseUI是它給你的火力地堡驗證頂部的預構建UI庫。

FirebaseUI需要配置(請參閱在選項文件做兩件事情):

  • 告訴FirebaseUI要使用電子郵件/密碼登錄方法。
  • 處理成功登錄的回調並返回 false 以避免重定向。您不希望頁面刷新,因為您正在構建單頁 Web 應用程序。

添加用於初始化 FirebaseUI Auth 的代碼

  1. 在StackBlitz,轉到index.js文件。
  2. 在頂部,找到firebase/auth import語句,再加入getAuthEmailAuthProvider ,像這樣:
    // ...
    // Add the Firebase products and methods that you want to use
    import { getAuth, EmailAuthProvider } from 'firebase/auth';
    
    import {} from 'firebase/firestore';
    
  3. 保存到auth對象的權利在經過了參考initializeApp ,像這樣:
    initializeApp(firebaseConfig);
    auth = getAuth();
    
  4. 請注意,FirebaseUI 配置已在起始代碼中提供。它已經設置為使用電子郵件身份驗證提供程序。
  5. 在底部main()函數index.js ,添加FirebaseUI初始化語句,像這樣:
    async function main() {
      // ...
    
      // Initialize the FirebaseUI widget using Firebase
      const ui = new firebaseui.auth.AuthUI(auth);
    }
    main();
    
    

向 HTML 添加 RSVP 按鈕

  1. 在StackBlitz,轉到index.html文件。
  2. 添加的HTML內部的RSVP按鈕event-details-container如下面的例子。

    小心使用相同的id值,如下圖所示,因為對於本程式碼實驗室,已經有鉤在這些特定ID index.js文件。

    注意,在index.html文件,有ID為容器firebaseui-auth-container 。這是您將傳遞給 FirebaseUI 以保存您的登錄信息的 ID。
    <!-- ... -->
    
    <section id="event-details-container">
        <!-- ... -->
        <!-- ADD THE RSVP BUTTON HERE -->
        <button id="startRsvp">RSVP</button>
    </section>
    <hr>
    <section id="firebaseui-auth-container"></section>
    <!-- ... -->
    
    應用程序預覽
    ab9ad7d61bb7b28c.png
  3. 在 RSVP 按鈕上設置偵聽器並調用 FirebaseUI 啟動函數。這會告訴 FirebaseUI 您想要查看登錄窗口。

    下面的代碼添加到的底部main()函數index.js
    async function main() {
      // ...
    
      // Listen to RSVP button clicks
      startRsvpButton.addEventListener("click",
       () => {
            ui.start("#firebaseui-auth-container", uiConfig);
      });
    }
    main();
    

測試登錄應用程序

  1. 在 StackBlitz 的預覽窗口中,單擊 RSVP 按鈕以登錄應用程序。
    • 對於此代碼實驗室,您可以使用任何電子郵件地址,甚至是虛假電子郵件地址,因為您沒有為此代碼實驗室設置電子郵件驗證步驟。
    • 如果你看到一個錯誤信息,指出auth/operation-not-allowedThe given sign-in provider is disabled for this Firebase project ,檢查,以確保您啟用電子郵件/密碼作為火力地堡控制台登錄提供商。
    應用預覽
    3024f90b52ad55fe.png
  2. 轉至驗證儀表盤的火力地堡控制台。在用戶選項卡,你應該看到在該應用程序進入到標誌的帳戶信息。 682fc0eca86a99fc.png

向 UI 添加身份驗證狀態

接下來,確保 UI 反映您已登錄的事實。

您將使用 Firebase 身份驗證狀態偵聽器回調,它會在用戶登錄狀態發生變化時收到通知。如果當前有登錄用戶,您的應用程序會將“RSVP”按鈕切換為“註銷”按鈕。

  1. 在StackBlitz,轉到index.js文件。
  2. 在頂部,找到firebase/auth import語句,再加入signOutonAuthStateChanged ,像這樣:
    // ...
    // Add the Firebase products and methods that you want to use
    import {
      getAuth,
      EmailAuthProvider,
      signOut,
      onAuthStateChanged
    } from 'firebase/auth';
    
    import {} from 'firebase/firestore';
    
  3. 在底部添加以下代碼main()函數:
    async function main() {
      // ...
    
      // Listen to the current Auth state
      onAuthStateChanged(auth, user => {
        if (user) {
          startRsvpButton.textContent = 'LOGOUT';
        } else {
          startRsvpButton.textContent = 'RSVP';
        }
      });
    }
    main();
    
  4. 在按鈕監聽器中,檢查是否有當前用戶並註銷。要做到這一點,替換當前startRsvpButton.addEventListener :與下列
    // ...
    // Called when the user clicks the RSVP button
    startRsvpButton.addEventListener('click', () => {
      if (auth.currentUser) {
        // User is signed in; allows user to sign out
        signOut(auth);
      } else {
        // No user is signed in; allows user to sign in
        ui.start('#firebaseui-auth-container', uiConfig);
      }
    });
    

現在,在您的應用程序的按鈕應該顯示註銷,並單擊時,應該切換回RSVP。

應用預覽

4c540450924f1607.png

知道用戶來了很好,但讓我們在應用程序中給客人一些其他的事情。如果他們可以在留言簿中留言怎麼辦?他們可以分享為什麼他們很高興來到這里或他們希望見到誰。

要存儲用戶在應用程序寫入聊天消息,您將使用雲計算公司的FireStore

數據模型

Cloud Firestore 是一個 NoSQL 數據庫,存儲在數據庫中的數據被拆分為集合、文檔、字段和子集合。你會聊天的每封郵件存儲為稱為頂級集合文檔guestbook

b447950f9f993789.png

將消息添加到 Firestore

在本節中,您將為用戶添加將新消息寫入數據庫的功能。首先,為 UI 元素(消息字段和發送按鈕)添加 HTML。然後,添加將這些元素連接到數據庫的代碼。

添加消息字段和發送按鈕的 UI 元素:

  1. 在StackBlitz,轉到index.html文件。
  2. 找到guestbook-container ,然後添加以下HTML創建與所述消息輸入字段和發送按鈕的形式。
    <!-- ... -->
    
     <section id="guestbook-container">
       <h2>Discussion</h2>
    
       <form id="leave-message">
         <label>Leave a message: </label>
         <input type="text" id="message">
         <button type="submit">
           <i class="material-icons">send</i>
           <span>SEND</span>
         </button>
       </form>
    
     </section>
    
    <!-- ... -->
    

應用預覽

4a892284443cf73d.png

單擊發送按鈕的用戶將觸發下面的代碼段。它增加了消息輸入字段的內容向guestbook數據庫的集合。具體而言, addDoc方法將所述消息內容到一個新的文件(帶有自動生成ID)到guestbook集合。

  1. 在StackBlitz,轉到index.js文件。
  2. 在頂部,找到firebase/firestore import語句,再加入getFirestoreaddDoc ,並collection ,像這樣:
    // ...
    
    // Add the Firebase products and methods that you want to use
    import {
      getAuth,
      EmailAuthProvider,
      signOut,
      onAuthStateChanged
    } from 'firebase/auth';
    
    import {
      getFirestore,
      addDoc,
      collection
    } from 'firebase/firestore';
    
  3. 現在,我們可以節省參考公司的FireStore db之後客體的權利initializeApp
    initializeApp(firebaseConfig);
    auth = getAuth();
    db = getFirestore();
    
  4. 在底部main()函數中,添加以下代碼。

    需要注意的是auth.currentUser.uid是自動生成的唯一ID的引用火力地堡認證給所有登錄的用戶。
    async function main() {
      // ...
    
      // Listen to the form submission
      form.addEventListener('submit', async e => {
        // Prevent the default form redirect
        e.preventDefault();
        // Write a new message to the database collection "guestbook"
        addDoc(collection(db, 'guestbook'), {
          text: input.value,
          timestamp: Date.now(),
          name: auth.currentUser.displayName,
          userId: auth.currentUser.uid
        });
        // clear message input field
        input.value = '';
        // Return false to avoid redirect
        return false;
      });
    }
    main();
    

僅向登錄用戶顯示留言簿

你不想只是任何人看到客人聊天。您可以為確保聊天安全所做的一件事是僅允許登錄用戶查看留言簿。這就是說,對於自己的應用程序,你會想也保護你的數據庫火力地堡的安全規則。 (稍後在代碼實驗室中有更多關於安全規則的信息。)

  1. 在StackBlitz,轉到index.js文件。
  2. 編輯onAuthStateChanged聽眾隱藏和顯示的留言。
    // ...
    
    // Listen to the current Auth state
    onAuthStateChanged(auth, user => {
      if (user) {
        startRsvpButton.textContent = 'LOGOUT';
        // Show guestbook to logged-in users
        guestbookContainer.style.display = 'block';
      } else {
        startRsvpButton.textContent = 'RSVP';
        // Hide guestbook for non-logged-in users
        guestbookContainer.style.display = 'none';
      }
    });
    

測試發送消息

  1. 確保您已登錄該應用。
  2. 輸入消息,如“嘿!”,然後單擊發送

此操作會將消息寫入您的 Cloud Firestore 數據庫。但是,您還不會在實際的 Web 應用程序中看到該消息,因為您仍然需要實現檢索數據。你接下來會這樣做。

但是您可以在 Firebase 控制台中看到新添加的消息。

在火力地堡控制台,在數據庫儀表板,你應該看到guestbook的收集與新添加的消息。如果您繼續發送消息,您的留言簿將包含許多文檔,如下所示:

Firebase 控制台

713870af0b3b63c.png

同步消息

客人可以將消息寫入數據庫,但他們還無法在應用程序中看到它們,這真是太好了。

要顯示消息,您需要添加在數據更改時觸發的偵聽器,然後創建一個顯示新消息的 UI 元素。

您將添加用於偵聽來自應用程序的新添加消息的代碼。首先,在 HTML 中添加一個部分以顯示消息:

  1. 在StackBlitz,轉到index.html文件。
  2. guestbook-container中,添加用的ID的新的部分guestbook
    <!-- ... -->
    
      <section id="guestbook-container">
       <h2>Discussion</h2>
    
       <form><!-- ... --></form>
    
       <section id="guestbook"></section>
    
     </section>
    
    <!-- ... -->
    

接下來,註冊偵聽對數據所做更改的偵聽器:

  1. 在StackBlitz,轉到index.js文件。
  2. 在頂部,找到firebase/firestore import語句,再加入queryorderBy ,並onSnapshot ,像這樣:
    // ...
    import {
      getFirestore,
      addDoc,
      collection,
      query,
      orderBy,
      onSnapshot
    } from 'firebase/firestore';
    
  3. 在底部main()函數,通過在數據庫中的所有文檔(留言信息)添加以下代碼迴路。要了解有關此代碼中發生的事情的更多信息,請閱讀代碼段下方的信息。
    async function main() {
      // ...
    
      // Create query for messages
      const q = query(collection(db, 'guestbook'), orderBy('timestamp', 'desc'));
      onSnapshot(q, snaps => {
        // Reset page
        guestbook.innerHTML = '';
        // Loop through documents in database
        snaps.forEach(doc => {
          // Create an HTML entry for each document and add it to the chat
          const entry = document.createElement('p');
          entry.textContent = doc.data().name + ': ' + doc.data().text;
          guestbook.appendChild(entry);
        });
      });
    }
    main();
    

要收聽數據庫中的信息,你已經通過創建一個特定集合的查詢collection功能。以上監聽中的變化的代碼guestbook集合,這是該聊天消息的存儲位置。該消息也由日期排序,使用orderBy('timestamp', 'desc')以顯示在頂部的最新消息。

onSnapshot函數有兩個參數:查詢使用和一個回調函數。當與查詢匹配的文檔發生任何更改時,將觸發回調函數。這可能是因為消息被刪除、修改或添加。欲了解更多信息,請參閱雲公司的FireStore文檔

測試同步消息

Cloud Firestore 會自動、即時地與訂閱數據庫的客戶端同步數據。

  • 您之前在數據庫中創建的消息應顯示在應用程序中。隨意編寫新消息;他們應該立即出現。
  • 如果您在多個窗口或選項卡中打開工作區,消息將跨選項卡實時同步。
  • (可選)可以嘗試手動刪除,修改,或直接在火力地堡控制台的數據庫部分添加新的消息;任何更改都應顯示在 UI 中。

恭喜!您正在應用中閱讀 Cloud Firestore 文檔!

應用預覽

e30df0a9614bae7d.png

您最初將 Cloud Firestore 設置為使用測試模式,這意味著您的數據庫可以讀寫。但是,您應該只在開發的早期階段使用測試模式。作為最佳實踐,您應該在開發應用程序時為數據庫設置安全規則。安全性應該是應用程序結構和行為不可或缺的一部分。

安全規則允許您控制對數據庫中文檔和集合的訪問。靈活的規則語法允許您創建規則,以匹配從對整個數據庫的所有寫入到對特定文檔的操作的任何內容。

您可以在 Firebase 控制台中為 Cloud Firestore 編寫安全規則:

  1. 在火力地堡控制台的Build部分,單擊數據庫的FireStore,然後選擇規則選項卡(或點擊這裡直接進入到規則選項卡)。
  2. 您應該會看到以下默認安全規則,以及有關規則公開的警告。

7767a2d2e64e7275.png

識別集合

首先,確定應用程序寫入數據的集合。

match /databases/{database}/documents ,確定要保護的集合:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /guestbook/{entry} {
     // You'll add rules here in the next step.
  }
}

添加安全規則

因為您使用身份驗證 UID 作為每個留言簿文檔中的一個字段,所以您可以獲得身份驗證 UID 並驗證任何嘗試寫入文檔的人都具有匹配的身份驗證 UID。

將讀寫規則添加到您的規則集中,如下所示:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /guestbook/{entry} {
      allow read: if request.auth.uid != null;
      allow create:
        if request.auth.uid == request.resource.data.userId;
    }
  }
}

現在,對於留言簿,只有登錄用戶才能閱讀消息(任何消息!),但您只能使用您的用戶 ID 創建消息。我們也不允許編輯或刪除消息。

添加驗證規則

添加數據驗證以確保文檔中存在所有預期字段:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /guestbook/{entry} {
      allow read: if request.auth.uid != null;
      allow create:
      if request.auth.uid == request.resource.data.userId
          && "name" in request.resource.data
          && "text" in request.resource.data
          && "timestamp" in request.resource.data;
    }
  }
}

重置監聽器

因為您的應用程序現在只允許通過認證的用戶登錄,你應該將留言簿firestore驗證監聽器裡查詢。否則會出現權限錯誤,當用戶退出時,應用程序將斷開連接。

  1. 拉留言收集onSnapshot監聽到一個所謂的新功能subscribeGuestbook 。另外,分配結果onSnapshot功能的guestbookListener變量。

    該公司的FireStore onSnapshot監聽器返回的退訂功能,你就可以使用以後取消快照聽眾。
    // ...
    // Listen to guestbook updates
    // Listen to guestbook updates
    function subscribeGuestbook() {
      const q = query(collection(db, 'guestbook'), orderBy('timestamp', 'desc'));
      guestbookListener = onSnapshot(q, snaps => {
        // Reset page
        guestbook.innerHTML = '';
        // Loop through documents in database
        snaps.forEach(doc => {
          // Create an HTML entry for each document and add it to the chat
          const entry = document.createElement('p');
          entry.textContent = doc.data().name + ': ' + doc.data().text;
          guestbook.appendChild(entry);
        });
      });
    }
    
  2. 添加一個新功能叫下面unsubscribeGuestbook 。檢查是否guestbookListener變量不為空,然後打電話取消監聽功能。
    // ...
    // Unsubscribe from guestbook updates
    function unsubscribeGuestbook() {
      if (guestbookListener != null) {
        guestbookListener();
        guestbookListener = null;
      }
    }
    

最後,添加新的功能到onAuthStateChanged回調。

  1. 加入subscribeGuestbook()在底部if (user)
  2. 加入unsubscribeGuestbook()在底部else說法。
    // ...
    // Listen to the current Auth state
    onAuthStateChanged(auth, user => {
      if (user) {
        startRsvpButton.textContent = 'LOGOUT';
        // Show guestbook to logged-in users
        guestbookContainer.style.display = 'block';
        // Subscribe to the guestbook collection
        subscribeGuestbook();
      } else {
        startRsvpButton.textContent = 'RSVP';
        // Hide guestbook for non-logged-in users
        guestbookContainer.style.display = 'none';
        // Unsubscribe from the guestbook collection
        unsubscribeGuestbook();
      }
    });
    

記錄與會者的回复狀態

現在,您的應用只允許人們在對活動感興趣時開始聊天。此外,您知道某人是否來的唯一方法是他們是否在聊天中發布。讓我們組織起來,讓人們知道有多少人要來。

您將添加一個開關來註冊想要參加活動的人,然後收集來的人數。

  1. 在StackBlitz,轉到index.html文件。
  2. guestbook-container ,添加一組按鈕,像這樣:
    <!-- ... -->
      <section id="guestbook-container">
       <h2>Are you attending?</h2>
         <button id="rsvp-yes">YES</button>
         <button id="rsvp-no">NO</button>
    
       <h2>Discussion</h2>
    
       <!-- ... -->
    
     </section>
    <!-- ... -->
    

應用預覽

73ca99ca35c13ee7.png

接下來,為按鈕點擊註冊監聽器。如果用戶點擊YES,然後利用自己的身份驗證UID保存到數據庫的響應。

  1. 在StackBlitz,轉到index.js文件。
  2. 在頂部,找到firebase/firestore import語句,然後添加docsetDoc ,並where ,像這樣:
    // ...
    // Add the Firebase products and methods that you want to use
    import {
      getFirestore,
      addDoc,
      collection,
      query,
      orderBy,
      onSnapshot,
      doc,
      setDoc,
      where
    } from 'firebase/firestore';
    
  3. 在底部main()函數,添加以下代碼聽RSVP狀態:
    async function main() {
      // ...
    
      // Listen to RSVP responses
      rsvpYes.onclick = async () => {
      };
      rsvpNo.onclick = async () => {
      };
    }
    main();
    
    
  4. 創建一個名為新收集attendees ,然後註冊一個文件引用,如果被點擊或者回复按鈕。
  5. 設置參照truefalse取決於被點擊了哪個按鈕。

    首先, rsvpYes
    // ...
    // Listen to RSVP responses
    rsvpYes.onclick = async () => {
      // Get a reference to the user's document in the attendees collection
      const userRef = doc(db, 'attendees', auth.currentUser.uid);
    
      // If they RSVP'd yes, save a document with attendi()ng: true
      try {
        await setDoc(userRef, {
          attending: true
        });
      } catch (e) {
        console.error(e);
      }
    };
    
    然後,同為rsvpNo ,但與價值false
    rsvpNo.onclick = async () => {
      // Get a reference to the user's document in the attendees collection
      const userRef = doc(db, 'attendees', auth.currentUser.uid);
    
      // If they RSVP'd yes, save a document with attending: true
      try {
        await setDoc(userRef, {
          attending: false
        });
      } catch (e) {
        console.error(e);
      }
    };
    

添加規則

因為您已經設置了一些規則,所以您使用按鈕添加的新數據將被拒絕。你將需要更新的規則允許添加到attendees集合。

對於attendees集合,因為你使用的認證UID為文件名,就可以抓住它,並確認提交的uid是一樣的,他們正在編寫的文檔。您將允許每個人閱讀與會者列表(因為那裡沒有私人數據),但只有創建者才能更新它。

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // ... //
    match /attendees/{userId} {
      allow read: if true;
      allow write: if request.auth.uid == userId;
    }
  }
}

添加驗證規則

添加數據驗證以確保文檔中存在所有預期字段:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // ... //
    match /attendees/{userId} {
      allow read: if true;
      allow write: if request.auth.uid == userId
          && "attending" in request.resource.data;

    }
  }
}

(可選)您現在可以查看點擊按鈕的結果。轉到 Firebase 控制台中的 Cloud Firestore 信息中心。

讀取 RSVP 狀態

現在您已經記錄了響應,讓我們看看誰來了並在 UI 中反映它。

  1. 在StackBlitz,轉到index.html文件。
  2. description-container ,添加一個新的元件用的ID number-attending
    <!-- ... -->
    
     <section id="description-container">
         <!-- ... -->
         <p id="number-attending"></p>
     </section>
    
    <!-- ... -->
    

接下來,註冊為聽眾attendees收集和計算的響應的數量:

  1. 在StackBlitz,轉到index.js文件。
  2. 在底部main()函數,添加以下代碼聽RSVP狀態和計算點擊。
    async function main() {
      // ...
    
      // Listen for attendee list
      const attendingQuery = query(
        collection(db, 'attendees'),
        where('attending', '==', true)
      );
      const unsubscribe = onSnapshot(attendingQuery, snap => {
        const newAttendeeCount = snap.docs.length;
        numberAttending.innerHTML = newAttendeeCount + ' people going';
      });
    }
    main();
    

最後,讓我們突出顯示當前狀態對應的按鈕。

  1. 創建一個函數,檢查是否當前的認證UID具有在一個條目attendees集合,然後設置按鈕的類來clicked
    // ...
    // Listen for attendee list
    function subscribeCurrentRSVP(user) {
      const ref = doc(db, 'attendees', user.uid);
      rsvpListener = onSnapshot(ref, doc => {
        if (doc && doc.data()) {
          const attendingResponse = doc.data().attending;
    
          // Update css classes for buttons
          if (attendingResponse) {
            rsvpYes.className = 'clicked';
            rsvpNo.className = '';
          } else {
            rsvpYes.className = '';
            rsvpNo.className = 'clicked';
          }
        }
      });
    }
    
  2. 另外,讓我們製作一個取消訂閱的功能。這將在用戶註銷時使用。
    // ...
    function unsubscribeCurrentRSVP() {
      if (rsvpListener != null) {
        rsvpListener();
        rsvpListener = null;
      }
      rsvpYes.className = '';
      rsvpNo.className = '';
    }
    
  3. 從身份驗證偵聽器調用函數。
    // ...
    // Listen to the current Auth state
      // Listen to the current Auth state
      onAuthStateChanged(auth, user => {
        if (user) {
          startRsvpButton.textContent = 'LOGOUT';
          // Show guestbook to logged-in users
          guestbookContainer.style.display = 'block';
    
          // Subscribe to the guestbook collection
          subscribeGuestbook();
          // Subcribe to the user's RSVP
          subscribeCurrentRSVP(user);
        } else {
          startRsvpButton.textContent = 'RSVP';
          // Hide guestbook for non-logged-in users
          guestbookContainer.style.display = 'none'
          ;
          // Unsubscribe from the guestbook collection
          unsubscribeGuestbook();
          // Unsubscribe from the guestbook collection
          unsubscribeCurrentRSVP();
        }
      });
    
  4. 嘗試登錄了多個用戶,看到每增加一個YES鍵點擊計數增加。

應用預覽

3df607d3e0b3c35.png

您已經使用 Firebase 構建了一個交互式實時 Web 應用程序!

我們涵蓋的內容

  • Firebase 身份驗證
  • Firebase用戶界面
  • 雲防火牆
  • Firebase 安全規則

下一步

了解更多

進展如何?

我們希望得到您的反饋!請填寫一個(非常)簡短的形式在這裡