ทำความรู้จัก Firebase สำหรับเว็บ

1. ภาพรวม

ในโค้ดแล็บนี้ คุณจะได้เรียนรู้ข้อมูลเบื้องต้นเกี่ยวกับ Firebase ในการสร้างเว็บแอปพลิเคชันแบบอินเทอร์แอกทีฟ คุณจะได้สร้างแอป RSVP ของกิจกรรมและแอปแชทสมุดเยี่ยมโดยใช้ผลิตภัณฑ์ Firebase หลายรายการ

ภาพหน้าจอของขั้นตอนนี้

สิ่งที่คุณจะได้เรียนรู้

  • ตรวจสอบสิทธิ์ผู้ใช้ด้วย Firebase Authentication และ FirebaseUI
  • ซิงค์ข้อมูลโดยใช้ Cloud Firestore
  • เขียนกฎการรักษาความปลอดภัยของ Firebase เพื่อรักษาความปลอดภัยของฐานข้อมูล

สิ่งที่ต้องมี

  • เบราว์เซอร์ที่คุณเลือก เช่น Chrome
  • สิทธิ์เข้าถึง stackblitz.com (ไม่ต้องมีบัญชีหรือลงชื่อเข้าใช้)
  • บัญชี Google เช่น บัญชี Gmail เราขอแนะนำให้ใช้บัญชีอีเมลที่คุณใช้กับบัญชี GitHub อยู่แล้ว ซึ่งจะช่วยให้คุณใช้ฟีเจอร์ขั้นสูงใน StackBlitz ได้
  • โค้ดตัวอย่างของโค้ดแล็บ ดูวิธีรับรหัสในขั้นตอนถัดไป

2. รับรหัสเริ่มต้น

ในโค้ดแล็บนี้ คุณจะได้สร้างแอปโดยใช้ StackBlitz ซึ่งเป็นเครื่องมือแก้ไขออนไลน์ที่ผสานรวมเวิร์กโฟลว์ Firebase หลายรายการไว้ด้วยกัน Stackblitz ไม่จำเป็นต้องติดตั้งซอฟต์แวร์หรือบัญชี StackBlitz พิเศษ

StackBlitz ช่วยให้คุณแชร์โปรเจ็กต์กับผู้อื่นได้ ผู้อื่นที่มี URL โปรเจ็กต์ StackBlitz ของคุณจะเห็นโค้ดและแยกโปรเจ็กต์ของคุณได้ แต่จะแก้ไขโปรเจ็กต์ StackBlitz ไม่ได้

  1. ไปที่ URL นี้เพื่อดูโค้ดเริ่มต้น: https://stackblitz.com/edit/firebase-gtk-web-start
  2. คลิกแยกที่ด้านบนของหน้า StackBlitz

ภาพหน้าจอของขั้นตอนนี้

ตอนนี้คุณมีสำเนาโค้ดเริ่มต้นเป็นโปรเจ็กต์ StackBlitz ของคุณเองซึ่งมีชื่อที่ไม่ซ้ำกัน รวมถึง URL ที่ไม่ซ้ำกัน ระบบจะบันทึกไฟล์และการเปลี่ยนแปลงทั้งหมดในโปรเจ็กต์ StackBlitz นี้

3. แก้ไขข้อมูลกิจกรรม

เนื้อหาเริ่มต้นสําหรับ Codelab นี้จะจัดโครงสร้างสําหรับเว็บแอป ซึ่งรวมถึงสไตลชีตและคอนเทนเนอร์ HTML 2-3 รายการสําหรับแอป ในภายหลังของ Codelab นี้ คุณจะเชื่อมต่อคอนเทนเนอร์เหล่านี้กับ Firebase

มาเริ่มทำความคุ้นเคยกับอินเทอร์เฟซของ StackBlitz กันก่อน

  1. เปิดไฟล์ index.html ใน StackBlitz
  2. ค้นหา event-details-container และ description-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>

<!-- ... -->

ตัวอย่างของแอปควรมีลักษณะดังนี้

ตัวอย่างแอป

ภาพหน้าจอของขั้นตอนนี้

4. สร้างและตั้งค่าโปรเจ็กต์ Firebase

การแสดงข้อมูลกิจกรรมเป็นสิ่งที่ดีสำหรับผู้เข้าร่วม แต่การแสดงกิจกรรมเพียงอย่างเดียวนั้นไม่ค่อยมีประโยชน์สำหรับทุกคน มาเพิ่มฟังก์ชันการทำงานแบบไดนามิกลงในแอปนี้กัน โดยคุณจะต้องเชื่อมต่อ Firebase กับแอป หากต้องการเริ่มต้นใช้งาน Firebase คุณจะต้องสร้างและตั้งค่าโปรเจ็กต์ Firebase

สร้างโปรเจ็กต์ Firebase

  1. ลงชื่อเข้าใช้ Firebase
  2. ในคอนโซล Firebase ให้คลิกเพิ่มโปรเจ็กต์ (หรือสร้างโปรเจ็กต์) จากนั้นตั้งชื่อโปรเจ็กต์ Firebase เป็น Firebase-Web-Codelab

    ภาพหน้าจอของขั้นตอนนี้

  3. คลิกตัวเลือกการสร้างโปรเจ็กต์ ยอมรับข้อกำหนดของ Firebase หากได้รับข้อความแจ้ง ในหน้าจอ Google Analytics ให้คลิก "ไม่เปิดใช้" เนื่องจากคุณจะไม่ได้ใช้ Analytics สําหรับแอปนี้

ดูข้อมูลเพิ่มเติมเกี่ยวกับโปรเจ็กต์ Firebase ได้ที่ทําความเข้าใจโปรเจ็กต์ Firebase

เปิดใช้และตั้งค่าผลิตภัณฑ์ Firebase ในคอนโซล

แอปที่คุณกําลังสร้างใช้ผลิตภัณฑ์ Firebase หลายรายการสําหรับเว็บแอป ดังนี้

  • การตรวจสอบสิทธิ์ Firebase และ UI ของ Firebase เพื่ออนุญาตให้ผู้ใช้ลงชื่อเข้าใช้แอปได้อย่างง่ายดาย
  • Cloud Firestore เพื่อบันทึก Structured Data ในระบบคลาวด์และรับการแจ้งเตือนทันทีเมื่อมีการเปลี่ยนแปลงข้อมูล
  • กฎการรักษาความปลอดภัยของ Firebase เพื่อรักษาความปลอดภัยให้ฐานข้อมูล

ผลิตภัณฑ์เหล่านี้บางรายการต้องมีการกําหนดค่าพิเศษหรือต้องเปิดใช้โดยใช้คอนโซล Firebase

เปิดใช้การลงชื่อเข้าใช้ด้วยอีเมลสําหรับการตรวจสอบสิทธิ์ Firebase

หากต้องการอนุญาตให้ผู้ใช้ลงชื่อเข้าใช้เว็บแอป คุณจะใช้วิธีการลงชื่อเข้าใช้ด้วยอีเมล/รหัสผ่านในโค้ดแล็บนี้

  1. ในแผงด้านซ้ายของคอนโซล Firebase ให้คลิกสร้าง > การตรวจสอบสิทธิ์ จากนั้นคลิกเริ่มต้นใช้งาน ตอนนี้คุณอยู่ในแดชบอร์ดการตรวจสอบสิทธิ์ ซึ่งคุณสามารถดูผู้ใช้ที่ลงชื่อสมัครใช้ กำหนดค่าผู้ให้บริการลงชื่อเข้าใช้ และจัดการการตั้งค่าได้

    ภาพหน้าจอของขั้นตอนนี้

  2. เลือกแท็บวิธีการลงชื่อเข้าใช้ (หรือคลิกที่นี่เพื่อไปที่แท็บนั้นโดยตรง)

    ภาพหน้าจอของขั้นตอนนี้

  3. คลิกอีเมล/รหัสผ่านจากตัวเลือกผู้ให้บริการ สลับสวิตช์เป็นเปิดใช้ แล้วคลิกบันทึก

    ภาพหน้าจอของขั้นตอนนี้

ตั้งค่า Cloud Firestore

เว็บแอปใช้ Cloud Firestore เพื่อบันทึกข้อความแชทและรับข้อความแชทใหม่

วิธีตั้งค่า Cloud Firestore ในโปรเจ็กต์ Firebase มีดังนี้

  1. ในแผงด้านซ้ายของคอนโซล Firebase ให้ขยายสร้าง แล้วเลือกฐานข้อมูล Firestore
  2. คลิกสร้างฐานข้อมูล
  3. ตั้งค่ารหัสฐานข้อมูลเป็น (default)
  4. เลือกตำแหน่งสำหรับฐานข้อมูล แล้วคลิกถัดไป
    สำหรับแอปจริง คุณควรเลือกตำแหน่งที่อยู่ใกล้กับผู้ใช้
  5. คลิกเริ่มในโหมดทดสอบ อ่านข้อจำกัดความรับผิดเกี่ยวกับกฎการรักษาความปลอดภัย
    ในภายหลังในโค้ดแล็บนี้ คุณจะเพิ่มกฎการรักษาความปลอดภัยเพื่อรักษาความปลอดภัยให้ข้อมูล อย่าเผยแพร่หรือแสดงแอปต่อสาธารณะโดยไม่เพิ่มกฎความปลอดภัยสําหรับฐานข้อมูล
  6. คลิกสร้าง

5. เพิ่มและกําหนดค่า Firebase

เมื่อสร้างโปรเจ็กต์ Firebase และเปิดใช้บริการบางอย่างแล้ว คุณต้องบอกโค้ดว่าต้องการใช้ Firebase รวมถึงโปรเจ็กต์ Firebase ที่จะใช้

เพิ่มไลบรารี Firebase

หากต้องการให้แอปใช้ Firebase คุณต้องเพิ่มไลบรารี Firebase ลงในแอป ซึ่งทําได้หลายวิธีตามที่อธิบายไว้ในเอกสารประกอบของ Firebase เช่น คุณสามารถเพิ่มไลบรารีจาก CDN ของ Google หรือจะติดตั้งในเครื่องโดยใช้ npm แล้วแพ็กเกจไว้ในแอปก็ได้หากใช้ Browserify

StackBlitz มีการรวมโดยอัตโนมัติเพื่อให้คุณเพิ่มไลบรารี Firebase โดยใช้คำสั่ง import ได้ คุณจะใช้ไลบรารีเวอร์ชันแบบแยกส่วน (v9) ซึ่งจะช่วยลดขนาดโดยรวมของหน้าเว็บผ่านกระบวนการที่เรียกว่า "Tree Shaking" ดูข้อมูลเพิ่มเติมเกี่ยวกับ SDK แบบแยกส่วนได้ในเอกสารประกอบ

คุณใช้ไลบรารี Firebase Authentication, FirebaseUI และ Cloud Firestore เพื่อสร้างแอปนี้ สําหรับโค้ดแล็บนี้ คำสั่งนําเข้าต่อไปนี้จะรวมอยู่ที่ด้านบนของไฟล์ index.js แล้ว และเราจะนําเข้าเมธอดเพิ่มเติมจากไลบรารี Firebase แต่ละรายการไปเรื่อยๆ

// 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 ลงในโปรเจ็กต์ Firebase

  1. กลับไปที่คอนโซล Firebase แล้วไปที่หน้าภาพรวมของโปรเจ็กต์โดยคลิกภาพรวมโปรเจ็กต์ที่ด้านซ้ายบน
  2. คลิกไอคอนเว็บ ไอคอนเว็บแอป ตรงกลางหน้าภาพรวมของโปรเจ็กต์เพื่อสร้างเว็บแอป Firebase ใหม่

    ภาพหน้าจอของขั้นตอนนี้

  3. ลงทะเบียนแอปโดยใช้ชื่อเล่นว่า Web App
  4. สําหรับโค้ดแล็บนี้ อย่าเลือกช่องข้างตั้งค่าโฮสติ้งของ Firebase สําหรับแอปนี้ด้วย คุณจะต้องใช้แผงแสดงตัวอย่างของ StackBlitz ในระหว่างนี้
  5. คลิกลงทะเบียนแอป

    ภาพหน้าจอของขั้นตอนนี้

  6. คัดลอกออบเจ็กต์การกําหนดค่า Firebase ไปยังคลิปบอร์ด

    ภาพหน้าจอของขั้นตอนนี้

  7. คลิกไปที่คอนโซล เพิ่มออบเจ็กต์การกําหนดค่า Firebase ลงในแอป โดยทําดังนี้
  8. กลับไปที่ StackBlitz แล้วไปที่ไฟล์ index.js
  9. ค้นหาบรรทัดความคิดเห็น Add Firebase project configuration object here แล้ววางข้อมูลโค้ดการกําหนดค่าใต้ความคิดเห็น
  10. เพิ่มinitializeAppการเรียกฟังก์ชันเพื่อตั้งค่า Firebase โดยใช้การกำหนดค่าโปรเจ็กต์ Firebase ที่ไม่ซ้ำกัน
    // ...
    // 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.firebasestorage.app",
      messagingSenderId: "random-unique-string",
      appId: "random-unique-string",
    };
    
    // Initialize Firebase
    initializeApp(firebaseConfig);
    

6. เพิ่มการลงชื่อเข้าใช้ของผู้ใช้ (คำตอบกลับ)

เมื่อเพิ่ม Firebase ลงในแอปแล้ว คุณจะตั้งค่าปุ่มตอบกลับที่ลงทะเบียนผู้ใช้โดยใช้ Firebase Authentication ได้

ตรวจสอบสิทธิ์ผู้ใช้ด้วยการลงชื่อเข้าใช้ด้วยอีเมลและ FirebaseUI

คุณจะต้องมีปุ่ม "ตอบกลับ" ที่แจ้งให้ผู้ใช้ลงชื่อเข้าใช้ด้วยอีเมล ซึ่งทำได้โดยเชื่อมต่อ FirebaseUI กับปุ่ม RSVP โดย FirebaseUI เป็นไลบรารีที่ให้ UI ที่สร้างขึ้นล่วงหน้าบน Firebase Auth

FirebaseUI ต้องมีการกําหนดค่า (ดูตัวเลือกในเอกสารประกอบ) ที่จะทํา 2 อย่างต่อไปนี้

  • บอก FirebaseUI ว่าคุณต้องการใช้วิธีการลงชื่อเข้าใช้ด้วยอีเมล/รหัสผ่าน
  • จัดการการเรียกกลับสําหรับการลงชื่อเข้าใช้ที่ประสบความสําเร็จและแสดงผลเป็นเท็จเพื่อหลีกเลี่ยงการเปลี่ยนเส้นทาง คุณไม่ต้องการให้หน้าเว็บรีเฟรชเนื่องจากกําลังสร้างเว็บแอปแบบหน้าเดียว

เพิ่มโค้ดเพื่อเริ่มต้น FirebaseUI Auth

  1. ใน StackBlitz ให้ไปที่ไฟล์ index.js
  2. ที่ด้านบน ให้ค้นหาคำสั่ง firebase/auth import แล้วเพิ่ม getAuth และ EmailAuthProvider ดังนี้
    // ...
    // Add the Firebase products and methods that you want to use
    import { getAuth, EmailAuthProvider } from 'firebase/auth';
    
    import {} from 'firebase/firestore';
    
  3. บันทึกการอ้างอิงไปยังออบเจ็กต์การตรวจสอบสิทธิ์ต่อจาก 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

  1. ใน StackBlitz ให้ไปที่ไฟล์ index.html
  2. เพิ่ม HTML สำหรับปุ่ม RSVP ภายใน event-details-container ดังที่แสดงในตัวอย่างด้านล่าง

    โปรดใช้ค่า id เดียวกันกับที่แสดงด้านล่าง เนื่องจากโค้ดแล็บนี้มีฮุกสําหรับรหัสที่เฉพาะเจาะจงเหล่านี้อยู่แล้วในไฟล์ index.js

    โปรดทราบว่าในไฟล์ index.html มีคอนเทนเนอร์ที่มีรหัส firebaseui-auth-container นี่คือรหัสที่คุณส่งไปยัง FirebaseUI เพื่อเก็บข้อมูลการเข้าสู่ระบบไว้
    <!-- ... -->
    
    <section id="event-details-container">
        <!-- ... -->
        <!-- ADD THE RSVP BUTTON HERE -->
        <button id="startRsvp">RSVP</button>
    </section>
    <hr>
    <section id="firebaseui-auth-container"></section>
    <!-- ... -->
    
    ตัวอย่างแอป

    ภาพหน้าจอของขั้นตอนนี้

  3. ตั้งค่า Listener ในปุ่ม 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-allowed หรือ The given sign-in provider is disabled for this Firebase project ให้ตรวจสอบว่าคุณได้เปิดใช้อีเมล/รหัสผ่านเป็นผู้ให้บริการลงชื่อเข้าใช้ในคอนโซล Firebase แล้ว
    ตัวอย่างแอป

    ภาพหน้าจอของขั้นตอนนี้

  2. ไปที่แดชบอร์ดการตรวจสอบสิทธิ์ในคอนโซล Firebase ในแท็บผู้ใช้ คุณควรเห็นข้อมูลบัญชีที่ป้อนเพื่อลงชื่อเข้าใช้แอป

    ภาพหน้าจอของขั้นตอนนี้

เพิ่มสถานะการตรวจสอบสิทธิ์ลงใน UI

ถัดไป ให้ตรวจสอบว่า UI แสดงว่าคุณลงชื่อเข้าใช้แล้ว

คุณจะใช้การเรียกกลับของโปรแกรมรับฟังสถานะการตรวจสอบสิทธิ์ Firebase ซึ่งจะได้รับการแจ้งเตือนทุกครั้งที่มีการเปลี่ยนแปลงสถานะการลงชื่อเข้าใช้ของผู้ใช้ หากมีผู้ใช้ที่ลงชื่อเข้าใช้อยู่ แอปจะเปลี่ยนปุ่ม "ตอบกลับ" เป็นปุ่ม "ออกจากระบบ"

  1. ใน StackBlitz ให้ไปที่ไฟล์ index.js
  2. ที่ด้านบน ให้ค้นหาคำสั่ง firebase/auth import แล้วเพิ่ม signOut และ onAuthStateChanged ดังนี้
    // ...
    // 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. ใน Listener ของปุ่ม ให้ตรวจสอบว่ามีผู้ใช้ปัจจุบันอยู่หรือไม่และออกจากระบบผู้ใช้รายนั้น โดยแทนที่ 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);
      }
    });
    
    ต่อไปนี้
    // ...
    // 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);
      }
    });
    

ตอนนี้ปุ่มในแอปควรแสดงเป็นออกจากระบบ และควรเปลี่ยนกลับไปเป็นตอบกลับเมื่อมีการคลิก

ตัวอย่างแอป

ภาพหน้าจอของขั้นตอนนี้

7. เขียนข้อความไปยัง Cloud Firestore

การรู้ว่าผู้ใช้เข้ามาเยี่ยมชมเป็นเรื่องที่ดี แต่อย่าลืมมอบสิ่งอื่นให้ผู้มาเยือนทำในแอปด้วย เช่น การให้ฝากข้อความในสมุดเยี่ยม โดยสามารถแชร์เหตุผลที่ตื่นเต้นที่จะเข้าร่วมหรือแชร์ว่าอยากเจอใคร

หากต้องการจัดเก็บข้อความแชทที่ผู้ใช้เขียนในแอป คุณจะใช้ Cloud Firestore

โมเดลข้อมูล

Cloud Firestore เป็นฐานข้อมูล NoSQL และข้อมูลที่จัดเก็บในฐานข้อมูลจะแบ่งออกเป็นคอลเล็กชัน เอกสาร ฟิลด์ และคอลเล็กชันย่อย คุณจะจัดเก็บข้อความแต่ละรายการของแชทเป็นเอกสารในคอลเล็กชันระดับบนสุดชื่อ guestbook

กราฟิกโมเดลข้อมูล Firestore ที่แสดงคอลเล็กชันสมุดเยี่ยมที่มีเอกสารข้อความหลายรายการ

เพิ่มข้อความลงใน Firestore

ในส่วนนี้ คุณจะต้องเพิ่มฟังก์ชันการทำงานเพื่อให้ผู้ใช้เขียนข้อความใหม่ลงในฐานข้อมูลได้ ก่อนอื่น ให้เพิ่ม HTML สำหรับองค์ประกอบ UI (ช่องข้อความและปุ่มส่ง) จากนั้นเพิ่มโค้ดที่เชื่อมโยงองค์ประกอบเหล่านี้กับฐานข้อมูล

วิธีเพิ่มองค์ประกอบ 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>
    
    <!-- ... -->
    

ตัวอย่างแอป

ภาพหน้าจอของขั้นตอนนี้

ผู้ใช้ที่คลิกปุ่มส่งจะเรียกข้อมูลโค้ดด้านล่างให้แสดง โดยจะเพิ่มเนื้อหาของช่องป้อนข้อความลงในคอลเล็กชัน guestbook ของฐานข้อมูล กล่าวโดยละเอียดคือ เมธอด addDoc จะเพิ่มเนื้อหาข้อความลงในเอกสารใหม่ (ที่มีรหัสที่สร้างขึ้นโดยอัตโนมัติ) ไปยังคอลเล็กชัน guestbook

  1. ใน StackBlitz ให้ไปที่ไฟล์ index.js
  2. ที่ด้านบน ให้ค้นหาfirebase/firestoreคำสั่งนําเข้า แล้วเพิ่ม getFirestore, addDoc และ 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. ตอนนี้เราจะบันทึกการอ้างอิงไปยังออบเจ็กต์ db ของ Firestore หลัง initializeApp ดังนี้
    initializeApp(firebaseConfig);
    auth = getAuth();
    db = getFirestore();
    
  4. เพิ่มโค้ดต่อไปนี้ที่ด้านล่างของฟังก์ชัน main()

    โปรดทราบว่า auth.currentUser.uid เป็นการอ้างอิงถึงรหัสที่ไม่ซ้ำกันซึ่งสร้างขึ้นโดยอัตโนมัติที่ Firebase Authentication มอบให้ผู้ใช้ที่เข้าสู่ระบบทั้งหมด
    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();
    

แสดงสมุดเยี่ยมต่อผู้ใช้ที่ลงชื่อเข้าใช้เท่านั้น

คุณไม่ต้องการให้ทุกคนเห็นแชทของผู้เข้าร่วม สิ่งหนึ่งที่คุณทำได้เพื่อรักษาความปลอดภัยของแชทคือการอนุญาตให้ผู้ใช้ที่ลงชื่อเข้าใช้เท่านั้นดูสมุดเยี่ยมได้ อย่างไรก็ตาม สําหรับแอปของคุณเอง คุณควรรักษาความปลอดภัยให้ฐานข้อมูลด้วยกฎความปลอดภัยของ Firebase ด้วย (ดูข้อมูลเพิ่มเติมเกี่ยวกับกฎความปลอดภัยได้ในโค้ดแล็บในภายหลัง)

  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 อย่างไรก็ตาม คุณจะยังไม่เห็นข้อความในเว็บแอปจริง เนื่องจากคุณยังต้องใช้การดึงข้อมูล คุณจะทำขั้นตอนดังกล่าวในลำดับถัดไป

แต่คุณจะเห็นข้อความที่เพิ่มใหม่ในคอนโซล Firebase

ในคอนโซล Firebase ในแดชบอร์ดฐานข้อมูล Firestore คุณควรเห็นคอลเล็กชัน guestbook ที่มีข้อความที่เพิ่มใหม่ หากคุณส่งข้อความอย่างต่อเนื่อง คอลเล็กชันสมุดเยี่ยมจะมีเอกสารจำนวนมาก ดังนี้

คอนโซล Firebase

ภาพหน้าจอของขั้นตอนนี้

8. อ่านข้อความ

ซิงค์ข้อความ

เป็นเรื่องดีที่ผู้มาเยือนสามารถเขียนข้อความลงในฐานข้อมูลได้ แต่ยังไม่อาจดูข้อความเหล่านั้นในแอป

หากต้องการแสดงข้อความ คุณจะต้องเพิ่ม Listeners ที่ทริกเกอร์เมื่อมีการเปลี่ยนแปลงข้อมูล จากนั้นสร้างองค์ประกอบ UI ที่แสดงข้อความใหม่

คุณจะต้องเพิ่มโค้ดที่คอยฟังข้อความที่เพิ่มใหม่จากแอป โดยเริ่มจากการเพิ่มส่วนใน HTML เพื่อแสดงข้อความ

  1. ใน StackBlitz ให้ไปที่ไฟล์ index.html
  2. ใน guestbook-container ให้เพิ่มส่วนใหม่ที่มีรหัส guestbook
    <!-- ... -->
    
      <section id="guestbook-container">
       <h2>Discussion</h2>
    
       <form><!-- ... --></form>
    
       <section id="guestbook"></section>
    
     </section>
    
    <!-- ... -->
    

ถัดไป ให้ลงทะเบียน Listener ที่คอยฟังการเปลี่ยนแปลงข้อมูล

  1. ใน StackBlitz ให้ไปที่ไฟล์ index.js
  2. ที่ด้านบน ให้ค้นหาfirebase/firestoreคำสั่งนําเข้า แล้วเพิ่ม query, orderBy และ 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 จะใช้พารามิเตอร์ 2 รายการ ได้แก่ คําค้นหาที่จะใช้และฟังก์ชัน Callback ระบบจะเรียกใช้ฟังก์ชัน Callback เมื่อเอกสารที่ตรงกับการค้นหามีการเปลี่ยนแปลง ซึ่งอาจเกิดขึ้นเมื่อมีการลบ แก้ไข หรือเพิ่มข้อความ ดูข้อมูลเพิ่มเติมได้ที่เอกสารประกอบ Cloud Firestore

ทดสอบการซิงค์ข้อความ

Cloud Firestore จะซิงค์ข้อมูลกับไคลเอ็นต์ที่สมัครใช้บริการฐานข้อมูลโดยอัตโนมัติและทันที

  • ข้อความที่คุณสร้างไว้ในฐานข้อมูลก่อนหน้านี้ควรแสดงในแอป คุณสามารถเขียนข้อความใหม่ได้ ซึ่งข้อความดังกล่าวจะปรากฏขึ้นทันที
  • หากคุณเปิดพื้นที่ทำงานในหลายหน้าต่างหรือแท็บ ข้อความจะซิงค์แบบเรียลไทม์ในแท็บต่างๆ
  • (ไม่บังคับ) คุณลองลบ แก้ไข หรือเพิ่มข้อความใหม่ด้วยตนเองได้ในส่วนฐานข้อมูลของคอนโซล Firebase โดยการเปลี่ยนแปลงจะปรากฏใน UI

ยินดีด้วย คุณกำลังอ่านเอกสาร Cloud Firestore ในแอป

ตัวอย่างแอป

ภาพหน้าจอของขั้นตอนนี้

9. ตั้งค่ากฎความปลอดภัยพื้นฐาน

ตอนแรกคุณตั้งค่า Cloud Firestore ให้ใช้โหมดทดสอบ ซึ่งหมายความว่าฐานข้อมูลจะเปิดสำหรับการอ่านและเขียน อย่างไรก็ตาม คุณควรใช้โหมดทดสอบในช่วงเริ่มต้นของการพัฒนาเท่านั้น แนวทางปฏิบัติแนะนำคือคุณควรตั้งค่ากฎความปลอดภัยสำหรับฐานข้อมูลขณะพัฒนาแอป ความปลอดภัยควรเป็นส่วนสำคัญของโครงสร้างและลักษณะการทํางานของแอป

กฎความปลอดภัยช่วยให้คุณควบคุมการเข้าถึงเอกสารและคอลเล็กชันในฐานข้อมูลได้ ไวยากรณ์กฎที่ยืดหยุ่นช่วยให้คุณสร้างกฎที่ตรงกับทุกสิ่งได้ ตั้งแต่การเขียนทั้งหมดไปยังทั้งฐานข้อมูลไปจนถึงการดำเนินการในเอกสารที่เฉพาะเจาะจง

คุณเขียนกฎการรักษาความปลอดภัยสำหรับ Cloud Firestore ได้ในคอนโซล Firebase โดยทำดังนี้

  1. ในส่วนบิลด์ของคอนโซล Firebase ให้คลิกฐานข้อมูล Firestore แล้วเลือกแท็บกฎ (หรือคลิกที่นี่เพื่อไปที่แท็บกฎโดยตรง)
  2. คุณควรเห็นกฎความปลอดภัยเริ่มต้นต่อไปนี้ ซึ่งมีการจำกัดเวลาการเข้าถึงแบบสาธารณะในอีก 2-3 สัปดาห์นับจากวันนี้

ภาพหน้าจอของขั้นตอนนี้

ระบุคอลเล็กชัน

ก่อนอื่น ให้ระบุคอลเล็กชันที่แอปเขียนข้อมูล

  1. ลบประโยค match /{document=**} ที่มีอยู่เพื่อให้กฎมีลักษณะดังนี้
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
      }
    }
    
  2. ใน 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 การตรวจสอบสิทธิ์ที่ตรงกัน

  1. เพิ่มกฎการอ่านและเขียนลงในชุดกฎดังที่แสดงด้านล่าง
    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;
        }
      }
    }
    
  2. คลิกเผยแพร่เพื่อใช้กฎใหม่ ตอนนี้สมุดเยี่ยมจะมีเฉพาะผู้ใช้ที่ลงชื่อเข้าใช้เท่านั้นที่อ่านข้อความได้ (ข้อความใดก็ได้) แต่คุณจะสร้างข้อความได้โดยใช้รหัสผู้ใช้เท่านั้น นอกจากนี้ เรายังไม่อนุญาตให้แก้ไขหรือลบข้อความ

เพิ่มกฎการตรวจสอบ

  1. เพิ่มการตรวจสอบข้อมูลเพื่อให้แน่ใจว่าช่องที่คาดไว้ทั้งหมดอยู่ในเอกสาร
    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;
        }
      }
    }
    
  2. คลิกเผยแพร่เพื่อติดตั้งใช้งานกฎใหม่

รีเซ็ต Listener

เนื่องจากตอนนี้แอปของคุณอนุญาตให้ผู้ใช้ที่ได้รับการตรวจสอบสิทธิ์เท่านั้นที่เข้าสู่ระบบได้ คุณจึงควรย้ายการค้นหา firestore สมุดเยี่ยมไปไว้ภายใน Listener การตรวจสอบสิทธิ์ มิฉะนั้น ระบบจะแสดงข้อผิดพลาดเกี่ยวกับสิทธิ์และแอปจะตัดการเชื่อมต่อเมื่อผู้ใช้ออกจากระบบ

  1. ใน StackBlitz ให้ไปที่ไฟล์ index.js
  2. ดึง onSnapshot listener ของคอลเล็กชันสมุดเยี่ยมไปไว้ในฟังก์ชันใหม่ที่ชื่อ subscribeGuestbook นอกจากนี้ ให้กําหนดผลลัพธ์ของฟังก์ชัน onSnapshot ให้กับตัวแปร guestbookListener

    ฟังก์ชัน onSnapshot Listener ของ Firestore จะแสดงผลฟังก์ชันยกเลิกการสมัครรับอีเมลที่คุณสามารถใช้เพื่อยกเลิก Listener ของสแนปชอตในภายหลัง
    // ...
    // 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);
        });
      });
    }
    
  3. เพิ่มฟังก์ชันใหม่ด้านล่างชื่อ unsubscribeGuestbook ตรวจสอบว่าตัวแปร guestbookListener ไม่ใช่ค่าว่าง จากนั้นเรียกใช้ฟังก์ชันเพื่อยกเลิก Listener
    // ...
    // Unsubscribe from guestbook updates
    function unsubscribeGuestbook() {
      if (guestbookListener != null) {
        guestbookListener();
        guestbookListener = null;
      }
    }
    

สุดท้าย ให้เพิ่มฟังก์ชันใหม่ลงใน onAuthStateChanged callback

  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();
      }
    });
    

10. ขั้นตอนพิเศษ: ฝึกฝนสิ่งที่ได้เรียนรู้

บันทึกสถานะการตอบกลับของแขก

ขณะนี้แอปของคุณอนุญาตให้ผู้ใช้เริ่มแชทได้หากสนใจกิจกรรม นอกจากนี้ วิธีเดียวที่คุณจะรู้ได้ว่ามีคนจะเข้าร่วมไหมก็คือเมื่อมีคนโพสต์ในแชท มาจัดระเบียบและแจ้งให้ทุกคนทราบว่าจะมีคนมาร่วมงานกี่คน

คุณจะเพิ่มปุ่มเปิด/ปิดเพื่อลงทะเบียนผู้ที่ต้องการเข้าร่วมกิจกรรม จากนั้นรวบรวมจํานวนผู้ที่จะมา

  1. ใน StackBlitz ให้ไปที่ไฟล์ index.html
  2. ใน guestbook-container ให้เพิ่มชุดปุ่ม YES และ NO ดังนี้
    <!-- ... -->
      <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>
    <!-- ... -->
    

ตัวอย่างแอป

ภาพหน้าจอของขั้นตอนนี้

ถัดไป ให้ลงทะเบียน Listener สําหรับการคลิกปุ่ม หากผู้ใช้คลิกใช่ ให้ใช้ UID การตรวจสอบสิทธิ์เพื่อบันทึกการตอบกลับลงในฐานข้อมูล

  1. ใน StackBlitz ให้ไปที่ไฟล์ index.js
  2. ที่ด้านบน ให้ค้นหาfirebase/firestoreคำสั่งนําเข้า แล้วเพิ่ม doc, setDoc และ 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() ให้เพิ่มโค้ดต่อไปนี้เพื่อฟังสถานะการตอบกลับ
    async function main() {
      // ...
    
      // Listen to RSVP responses
      rsvpYes.onclick = async () => {
      };
      rsvpNo.onclick = async () => {
      };
    }
    main();
    
    
  4. ถัดไป ให้สร้างคอลเล็กชันใหม่ชื่อ attendees จากนั้นลงทะเบียนการอ้างอิงเอกสารหากมีการคลิกปุ่ม RSVP ตั้งค่าข้อมูลอ้างอิงเป็น true หรือ false โดยขึ้นอยู่กับปุ่มที่คลิก

    ก่อนอื่นสำหรับ 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

  1. สำหรับคอลเล็กชัน attendees เนื่องจากคุณใช้ UID การตรวจสอบสิทธิ์เป็นชื่อเอกสาร คุณจึงสามารถดึงข้อมูล 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;
        }
      }
    }
    
  2. คลิกเผยแพร่เพื่อติดตั้งใช้งานกฎใหม่

เพิ่มกฎการตรวจสอบ

  1. เพิ่มกฎการตรวจสอบข้อมูลเพื่อให้แน่ใจว่าช่องที่คาดไว้ทั้งหมดอยู่ในเอกสาร
    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;
    
        }
      }
    }
    
  2. อย่าลืมคลิกเผยแพร่เพื่อใช้งานกฎ

(ไม่บังคับ) ตอนนี้คุณดูผลลัพธ์ของการคลิกปุ่มได้แล้ว ไปที่แดชบอร์ด Cloud Firestore ในคอนโซล Firebase

อ่านสถานะการตอบกลับ

เมื่อบันทึกคำตอบแล้ว เรามาดูกันว่าใครจะมาและแสดงข้อมูลใน UI

  1. ใน StackBlitz ให้ไปที่ไฟล์ index.html
  2. ใน description-container ให้เพิ่มองค์ประกอบใหม่ที่มีรหัส number-attending
    <!-- ... -->
    
     <section id="description-container">
         <!-- ... -->
         <p id="number-attending"></p>
     </section>
    
    <!-- ... -->
    

ถัดไป ให้ลงทะเบียนโปรแกรมฟังสําหรับคอลเล็กชัน attendees และนับจํานวนคําตอบที่ตอบว่าใช่

  1. ใน StackBlitz ให้ไปที่ไฟล์ index.js
  2. ที่ด้านล่างของฟังก์ชัน main() ให้เพิ่มโค้ดต่อไปนี้เพื่อรับฟังสถานะการตอบกลับและนับการคลิกใช่
    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. เรียกใช้ฟังก์ชันนี้จาก Listener การตรวจสอบสิทธิ์
    // ...
    // 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();
          // Subscribe 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. ลองเข้าสู่ระบบในฐานะผู้ใช้หลายคน แล้วดูว่าจำนวนเพิ่มขึ้นทุกครั้งที่คลิกปุ่มใช่

ตัวอย่างแอป

ภาพหน้าจอของขั้นตอนนี้

11. ยินดีด้วย

คุณใช้ Firebase เพื่อสร้างเว็บแอปพลิเคชันแบบเรียลไทม์ที่โต้ตอบได้แล้ว

สิ่งที่เราได้พูดถึง

  • การตรวจสอบสิทธิ์ Firebase
  • FirebaseUI
  • Cloud Firestore
  • กฎการรักษาความปลอดภัยของ Firebase

ขั้นตอนถัดไป

  • ต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับเวิร์กโฟลว์ของนักพัฒนาแอป Firebase ดูCodelab โปรแกรมจำลอง Firebase เพื่อดูวิธีทดสอบและเรียกใช้แอปในเครื่องโดยสมบูรณ์
  • ต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับผลิตภัณฑ์อื่นๆ ของ Firebase หรือคุณต้องการจัดเก็บไฟล์รูปภาพที่ผู้ใช้อัปโหลด หรือส่งการแจ้งเตือนไปยังผู้ใช้ ดูโค้ดแล็บ Firebase สำหรับเว็บ ซึ่งเป็นโค้ดแล็บที่เจาะลึกผลิตภัณฑ์ Firebase อื่นๆ อีกมากมายสำหรับเว็บ
  • ต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับ Cloud Firestore หรือต้องการดูข้อมูลเกี่ยวกับคอลเล็กชันย่อยและธุรกรรม ไปที่ Codelab เว็บของ Cloud Firestore เพื่อดู Codelab ที่เจาะลึกเกี่ยวกับ Cloud Firestore หรือดูซีรีส์ YouTube เพื่อทำความเข้าใจ Cloud Firestore

ดูข้อมูลเพิ่มเติม

ผลลัพธ์เป็นอย่างไรบ้าง

เราอยากทราบความคิดเห็นของคุณ โปรดกรอกแบบฟอร์มสั้นๆ (สั้นมาก) ที่นี่