1. Tổng quan
Trong lớp học lập trình này, bạn sẽ tìm hiểu một số kiến thức cơ bản về Firebase để tạo các ứng dụng web có tính tương tác. Bạn sẽ tạo một ứng dụng trò chuyện sổ lưu bút và ứng dụng RSVP sự kiện bằng cách sử dụng một số sản phẩm của Firebase.
Kiến thức bạn sẽ học được
- Xác thực người dùng bằng Xác thực Firebase và FirebaseUI.
- Đồng bộ hoá dữ liệu bằng Cloud Firestore.
- Viết các quy tắc bảo mật của Firebase để bảo mật cơ sở dữ liệu.
Bạn cần
- Một trình duyệt mà bạn chọn, chẳng hạn như Chrome.
- Truy cập vào stackblitz.com (không cần có tài khoản hoặc đăng nhập).
- Tài khoản Google, chẳng hạn như tài khoản Gmail. Bạn nên dùng tài khoản email mà bạn đang dùng cho tài khoản GitHub của mình. Nhờ đó, bạn có thể sử dụng các tính năng nâng cao trong StackBlitz.
- Mã mẫu của lớp học lập trình. Hãy xem bước tiếp theo để biết cách lấy mã.
2. Lấy mã khởi đầu
Trong lớp học lập trình này, bạn sẽ tạo một ứng dụng bằng StackBlitz, một trình chỉnh sửa trực tuyến có tích hợp một số quy trình Firebase. Stackblitz không yêu cầu bạn cài đặt phần mềm hoặc có tài khoản StackBlitz đặc biệt.
StackBlitz cho phép bạn chia sẻ dự án với người khác. Những người khác có URL dự án StackBlitz của bạn có thể xem mã và phân nhánh dự án của bạn, nhưng họ không thể chỉnh sửa dự án StackBlitz của bạn.
- Truy cập vào URL này để xem mã khởi đầu: https://stackblitz.com/edit/firebase-gtk-web-start
- Ở đầu trang StackBlitz, hãy nhấp vào Fork (Phân nhánh):
Giờ đây, bạn đã có một bản sao của mã khởi đầu dưới dạng dự án StackBlitz của riêng mình, có tên riêng biệt cùng với một URL riêng biệt. Tất cả tệp và nội dung thay đổi của bạn đều được lưu trong dự án StackBlitz này.
3. Chỉnh sửa thông tin sự kiện
Các tài liệu bắt đầu cho lớp học lập trình này cung cấp một số cấu trúc cho ứng dụng web, bao gồm một số biểu định kiểu và một vài vùng chứa HTML cho ứng dụng. Sau này trong lớp học lập trình này, bạn sẽ kết nối các vùng chứa này với Firebase.
Để bắt đầu, hãy làm quen thêm một chút với giao diện StackBlitz.
- Trong StackBlitz, hãy mở tệp
index.html
. - Tìm
event-details-container
vàdescription-container
, sau đó thử chỉnh sửa một số thông tin chi tiết về sự kiện.
Khi bạn chỉnh sửa văn bản, tính năng tự động tải lại trang trong StackBlitz sẽ hiển thị thông tin chi tiết mới về sự kiện. Ngầu đúng không?
<!-- ... -->
<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>
<!-- ... -->
Bản xem trước của ứng dụng sẽ có dạng như sau:
Bản xem trước ứng dụng
4. Tạo và thiết lập dự án Firebase
Việc hiển thị thông tin sự kiện rất hữu ích cho khách của bạn, nhưng chỉ hiển thị sự kiện thì không hữu ích cho bất kỳ ai. Hãy thêm một số chức năng động vào ứng dụng này. Để làm việc này, bạn cần kết nối Firebase với ứng dụng của mình. Để bắt đầu với Firebase, bạn cần tạo và thiết lập một dự án Firebase.
Tạo dự án Firebase
- Đăng nhập vào bảng điều khiển của Firebase bằng Tài khoản Google của bạn.
- Nhấp vào nút để tạo một dự án mới, sau đó nhập tên dự án (ví dụ:
Firebase-Web-Codelab
). - Nhấp vào Tiếp tục.
- Nếu được nhắc, hãy xem xét và chấp nhận các điều khoản của Firebase, rồi nhấp vào Tiếp tục.
- (Không bắt buộc) Bật tính năng hỗ trợ của AI trong bảng điều khiển của Firebase (còn gọi là "Gemini trong Firebase").
- Đối với lớp học lập trình này, bạn không cần Google Analytics, vì vậy hãy tắt lựa chọn Google Analytics.
- Nhấp vào Tạo dự án, đợi dự án được cấp phép rồi nhấp vào Tiếp tục.
Để tìm hiểu thêm về các dự án Firebase, hãy xem bài viết Tìm hiểu về các dự án Firebase.
Bật và thiết lập các sản phẩm của Firebase trong bảng điều khiển
Ứng dụng bạn đang tạo sử dụng một số sản phẩm Firebase có sẵn cho các ứng dụng web:
- Xác thực Firebase và Giao diện người dùng Firebase để dễ dàng cho phép người dùng đăng nhập vào ứng dụng của bạn.
- Cloud Firestore để lưu dữ liệu có cấu trúc trên đám mây và nhận thông báo tức thì khi dữ liệu thay đổi.
- Các quy tắc bảo mật của Firebase để bảo mật cơ sở dữ liệu của bạn.
Một số sản phẩm trong số này cần có cấu hình đặc biệt hoặc cần được bật bằng cách sử dụng bảng điều khiển của Firebase.
Bật tính năng đăng nhập bằng email cho tính năng Xác thực Firebase
Để cho phép người dùng đăng nhập vào ứng dụng web, bạn sẽ phải dùng phương thức đăng nhập Email/Mật khẩu cho lớp học lập trình này:
- Trong bảng điều khiển bên trái của bảng điều khiển Firebase, hãy nhấp vào Tạo > Xác thực. Sau đó, hãy nhấp vào Bắt đầu. Giờ đây, bạn đang ở trong trang tổng quan Xác thực, nơi bạn có thể xem người dùng đã đăng ký, định cấu hình nhà cung cấp dịch vụ đăng nhập và quản lý các chế độ cài đặt.
- Chọn thẻ Phương thức đăng nhập (hoặc nhấp vào đây để chuyển thẳng đến thẻ này).
- Nhấp vào Email/Mật khẩu trong các lựa chọn về nhà cung cấp, chuyển nút bật/tắt sang Bật, rồi nhấp vào Lưu.
Thiết lập Cloud Firestore
Ứng dụng web này sử dụng Cloud Firestore để lưu tin nhắn trò chuyện và nhận tin nhắn trò chuyện mới.
Sau đây là cách thiết lập Cloud Firestore trong dự án Firebase:
- Trong bảng điều khiển bên trái của bảng điều khiển Firebase, hãy mở rộng mục Tạo rồi chọn Cơ sở dữ liệu Firestore.
- Nhấp vào Tạo cơ sở dữ liệu.
- Để nguyên Mã cơ sở dữ liệu được đặt thành
(default)
. - Chọn một vị trí cho cơ sở dữ liệu của bạn, rồi nhấp vào Tiếp theo.
Đối với một ứng dụng thực tế, bạn nên chọn một vị trí gần với người dùng của mình. - Nhấp vào Bắt đầu ở chế độ thử nghiệm. Đọc tuyên bố từ chối trách nhiệm về các quy tắc bảo mật.
Sau này trong lớp học lập trình này, bạn sẽ thêm Quy tắc bảo mật để bảo mật dữ liệu của mình. Không phân phối hoặc công khai một ứng dụng mà không thêm Quy tắc bảo mật cho cơ sở dữ liệu của bạn. - Nhấp vào Tạo.
5. Thêm và định cấu hình Firebase
Giờ đây, khi đã tạo dự án Firebase và bật một số dịch vụ, bạn cần cho mã biết rằng bạn muốn sử dụng Firebase, cũng như dự án Firebase nào cần sử dụng.
Thêm các thư viện Firebase
Để ứng dụng của bạn sử dụng Firebase, bạn cần thêm các thư viện Firebase vào ứng dụng. Có nhiều cách để thực hiện việc này, như được mô tả trong tài liệu về Firebase. Ví dụ: bạn có thể thêm các thư viện từ CDN của Google hoặc bạn có thể cài đặt các thư viện đó cục bộ bằng npm rồi đóng gói chúng trong ứng dụng nếu đang dùng Browserify.
StackBlitz cung cấp tính năng kết hợp tự động, vì vậy bạn có thể thêm các thư viện Firebase bằng cách sử dụng câu lệnh nhập. Bạn sẽ sử dụng các phiên bản mô-đun (v9) của thư viện. Các phiên bản này giúp giảm kích thước tổng thể của trang web thông qua một quy trình gọi là "loại bỏ mã không dùng". Bạn có thể tìm hiểu thêm về các SDK theo mô-đun trong tài liệu.
Để tạo ứng dụng này, bạn sẽ sử dụng các thư viện Xác thực Firebase, FirebaseUI và Cloud Firestore. Trong lớp học lập trình này, các câu lệnh nhập sau đây đã được đưa vào đầu tệp index.js
và chúng ta sẽ nhập thêm các phương thức từ mỗi thư viện Firebase khi thực hiện:
// 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';
Thêm một ứng dụng web Firebase vào dự án Firebase
- Trong bảng điều khiển của Firebase, hãy chuyển đến trang tổng quan về dự án bằng cách nhấp vào Tổng quan về dự án ở trên cùng bên trái.
- Ở giữa trang tổng quan của dự án, hãy nhấp vào biểu tượng web
để tạo một ứng dụng web Firebase mới.
- Đăng ký ứng dụng bằng biệt hiệu Ứng dụng web.
- Đối với lớp học lập trình này, ĐỪNG đánh dấu vào hộp bên cạnh Đồng thời thiết lập Firebase Hosting cho ứng dụng này. Hiện tại, bạn sẽ sử dụng ngăn xem trước của StackBlitz.
- Nhấp vào Đăng ký ứng dụng.
- Sao chép đối tượng cấu hình Firebase vào bảng nhớ tạm.
- Nhấp vào Tiếp tục truy cập bảng điều khiển.Thêm đối tượng cấu hình Firebase vào ứng dụng của bạn:
- Quay lại StackBlitz, chuyển đến tệp
index.js
. - Tìm dòng nhận xét
Add Firebase project configuration object here
, sau đó dán đoạn mã cấu hình ngay bên dưới dòng nhận xét đó. - Thêm lệnh gọi hàm
initializeApp
để thiết lập Firebase bằng cấu hình dự án Firebase riêng biệt của bạn.// ... // 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. Thêm tính năng đăng nhập của người dùng (RSVP)
Giờ đây, khi đã thêm Firebase vào ứng dụng, bạn có thể thiết lập một nút RSVP để đăng ký người dùng bằng Xác thực Firebase.
Xác thực người dùng bằng tính năng Đăng nhập bằng email và FirebaseUI
Bạn cần có nút RSVP (xác nhận tham dự) để nhắc người dùng đăng nhập bằng địa chỉ email của họ. Bạn có thể làm việc này bằng cách kết nối FirebaseUI với nút RSVP.FirebaseUI là một thư viện cung cấp cho bạn giao diện người dùng được tạo sẵn trên Firebase Auth.
FirebaseUI yêu cầu một cấu hình (xem các lựa chọn trong tài liệu) thực hiện 2 việc:
- Cho FirebaseUI biết rằng bạn muốn sử dụng phương thức đăng nhập Email/Mật khẩu.
- Xử lý lệnh gọi lại cho một lần đăng nhập thành công và trả về giá trị false để tránh chuyển hướng. Bạn không muốn trang làm mới vì bạn đang tạo một ứng dụng web một trang.
Thêm mã để khởi chạy FirebaseUI Auth
- Trong StackBlitz, hãy chuyển đến tệp
index.js
. - Ở trên cùng, hãy tìm câu lệnh nhập
firebase/auth
, sau đó thêmgetAuth
vàEmailAuthProvider
, như sau:// ... // Add the Firebase products and methods that you want to use import { getAuth, EmailAuthProvider } from 'firebase/auth'; import {} from 'firebase/firestore';
- Lưu tham chiếu đến đối tượng uỷ quyền ngay sau
initializeApp
, như sau:initializeApp(firebaseConfig); auth = getAuth();
- Lưu ý rằng cấu hình FirebaseUI đã được cung cấp trong mã khởi đầu. Ứng dụng này đã được thiết lập để sử dụng trình cung cấp dịch vụ xác thực bằng email.
- Ở cuối hàm
main()
trongindex.js
, hãy thêm câu lệnh khởi chạy FirebaseUI như sau:async function main() { // ... // Initialize the FirebaseUI widget using Firebase const ui = new firebaseui.auth.AuthUI(auth); } main();
Thêm nút trả lời vào HTML
- Trong StackBlitz, hãy chuyển đến tệp
index.html
. - Thêm HTML cho nút hồi đáp vào bên trong
event-details-container
như minh hoạ trong ví dụ bên dưới.
Hãy cẩn thận khi sử dụng các giá trịid
giống như trong ví dụ bên dưới vì đối với lớp học lập trình này, đã có các hook cho những mã nhận dạng cụ thể này trong tệpindex.js
.
Lưu ý rằng trong tệpindex.html
, có một vùng chứa có mã nhận dạng làfirebaseui-auth-container
. Đây là mã nhận dạng mà bạn sẽ truyền đến FirebaseUI để giữ thông tin đăng nhập của mình. Bản xem trước ứng dụng<!-- ... --> <section id="event-details-container"> <!-- ... --> <!-- ADD THE RSVP BUTTON HERE --> <button id="startRsvp">RSVP</button> </section> <hr> <section id="firebaseui-auth-container"></section> <!-- ... -->
- Thiết lập một trình nghe trên nút RSVP và gọi hàm bắt đầu FirebaseUI. Thao tác này cho FirebaseUI biết rằng bạn muốn thấy cửa sổ đăng nhập.
Thêm mã sau vào cuối hàmmain()
trongindex.js
:async function main() { // ... // Listen to RSVP button clicks startRsvpButton.addEventListener("click", () => { ui.start("#firebaseui-auth-container", uiConfig); }); } main();
Kiểm thử việc đăng nhập vào ứng dụng
- Trong cửa sổ xem trước của StackBlitz, hãy nhấp vào nút RSVP để đăng nhập vào ứng dụng.
- Trong lớp học lập trình này, bạn có thể sử dụng bất kỳ địa chỉ email nào, kể cả địa chỉ email giả, vì bạn không thiết lập bước xác minh email cho lớp học lập trình này.
- Nếu bạn thấy thông báo lỗi cho biết
auth/operation-not-allowed
hoặcThe given sign-in provider is disabled for this Firebase project
, hãy kiểm tra để đảm bảo rằng bạn đã bật Email/Mật khẩu làm nhà cung cấp dịch vụ đăng nhập trong bảng điều khiển Firebase.
- Chuyển đến trang tổng quan Xác thực trong bảng điều khiển của Firebase. Trong thẻ Người dùng, bạn sẽ thấy thông tin tài khoản mà bạn đã nhập để đăng nhập vào ứng dụng.
Thêm trạng thái xác thực vào giao diện người dùng
Tiếp theo, hãy đảm bảo rằng giao diện người dùng phản ánh trạng thái đăng nhập của bạn.
Bạn sẽ sử dụng lệnh gọi lại của trình nghe trạng thái Xác thực Firebase. Lệnh gọi lại này sẽ nhận được thông báo mỗi khi trạng thái đăng nhập của người dùng thay đổi. Nếu hiện có người dùng đã đăng nhập, ứng dụng của bạn sẽ chuyển nút "RSVP" thành nút "đăng xuất".
- Trong StackBlitz, hãy chuyển đến tệp
index.js
. - Ở trên cùng, hãy tìm câu lệnh nhập
firebase/auth
, sau đó thêmsignOut
vàonAuthStateChanged
, như sau:// ... // Add the Firebase products and methods that you want to use import { getAuth, EmailAuthProvider, signOut, onAuthStateChanged } from 'firebase/auth'; import {} from 'firebase/firestore';
- Thêm mã sau vào cuối hàm
main()
:async function main() { // ... // Listen to the current Auth state onAuthStateChanged(auth, user => { if (user) { startRsvpButton.textContent = 'LOGOUT'; } else { startRsvpButton.textContent = 'RSVP'; } }); } main();
- Trong trình nghe nút, hãy kiểm tra xem có người dùng hiện tại hay không và đăng xuất họ. Để thực hiện việc này, hãy thay thế
startRsvpButton.addEventListener
hiện tại bằng đoạn mã sau:// ... // 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); } });
Giờ đây, nút trong ứng dụng của bạn sẽ hiển thị ĐĂNG XUẤT và chuyển về RSVP khi được nhấp.
Bản xem trước ứng dụng
7. Ghi thông báo vào Cloud Firestore
Việc biết rằng người dùng đang đến là điều tuyệt vời, nhưng hãy cho khách làm việc khác trong ứng dụng. Chuyện gì sẽ xảy ra nếu họ có thể để lại tin nhắn trong sổ lưu bút? Họ có thể chia sẻ lý do khiến họ hào hứng tham gia hoặc người mà họ hy vọng sẽ gặp.
Để lưu trữ các tin nhắn trò chuyện mà người dùng viết trong ứng dụng, bạn sẽ sử dụng Cloud Firestore.
Mô hình dữ liệu
Cloud Firestore là một cơ sở dữ liệu NoSQL và dữ liệu được lưu trữ trong cơ sở dữ liệu này được chia thành các tập hợp, tài liệu, trường và tập hợp con. Bạn sẽ lưu trữ từng tin nhắn của cuộc trò chuyện dưới dạng một tài liệu trong một tập hợp cấp cao nhất có tên là guestbook
.
Thêm thông báo vào Firestore
Trong phần này, bạn sẽ thêm chức năng để người dùng viết tin nhắn mới vào cơ sở dữ liệu. Trước tiên, bạn thêm HTML cho các phần tử trên giao diện người dùng (trường tin nhắn và nút gửi). Sau đó, bạn thêm mã kết nối các phần tử này với cơ sở dữ liệu.
Cách thêm các phần tử trên giao diện người dùng của một trường tin nhắn và một nút gửi:
- Trong StackBlitz, hãy chuyển đến tệp
index.html
. - Tìm
guestbook-container
, sau đó thêm HTML sau đây để tạo một biểu mẫu có trường nhập tin nhắn và nút gửi.<!-- ... --> <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> <!-- ... -->
Bản xem trước ứng dụng
Người dùng nhấp vào nút GỬI sẽ kích hoạt đoạn mã bên dưới. Thao tác này sẽ thêm nội dung của trường nhập thông báo vào tập hợp guestbook
của cơ sở dữ liệu. Cụ thể, phương thức addDoc
sẽ thêm nội dung thông báo vào một tài liệu mới (có mã nhận dạng được tạo tự động) vào bộ sưu tập guestbook
.
- Trong StackBlitz, hãy chuyển đến tệp
index.js
. - Ở trên cùng, hãy tìm câu lệnh nhập
firebase/firestore
, sau đó thêmgetFirestore
,addDoc
vàcollection
, như sau:// ... // 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';
- Bây giờ, chúng ta sẽ lưu tham chiếu đến đối tượng Firestore
db
ngay sauinitializeApp
:initializeApp(firebaseConfig); auth = getAuth(); db = getFirestore();
- Thêm mã sau vào cuối hàm
main()
.
Xin lưu ý rằngauth.currentUser.uid
là thông tin tham chiếu đến mã nhận dạng duy nhất được tạo tự động mà Xác thực Firebase cung cấp cho tất cả người dùng đã đăng nhập.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();
Chỉ cho phép người dùng đã đăng nhập xem sổ lưu bút
Bạn không muốn bất kỳ ai xem được cuộc trò chuyện của khách. Một việc bạn có thể làm để bảo mật cuộc trò chuyện là chỉ cho phép người dùng đã đăng nhập xem sổ lưu bút. Tuy nhiên, đối với các ứng dụng của riêng mình, bạn cũng nên bảo mật cơ sở dữ liệu bằng Quy tắc bảo mật của Firebase. (Bạn có thể xem thêm thông tin về các quy tắc bảo mật ở phần sau của lớp học lập trình này.)
- Trong StackBlitz, hãy chuyển đến tệp
index.js
. - Chỉnh sửa trình nghe
onAuthStateChanged
để ẩn và hiện sổ lưu bút.// ... // 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'; } });
Kiểm thử việc gửi tin nhắn
- Đảm bảo rằng bạn đã đăng nhập vào ứng dụng.
- Nhập một tin nhắn, chẳng hạn như "Chào bạn!", rồi nhấp vào GỬI.
Hành động này sẽ ghi thông báo vào cơ sở dữ liệu Cloud Firestore của bạn. Tuy nhiên, bạn sẽ chưa thấy thông báo này trong ứng dụng web thực tế vì bạn vẫn cần triển khai việc truy xuất dữ liệu. Bạn sẽ thực hiện việc đó ở bước tiếp theo.
Tuy nhiên, bạn có thể thấy thông báo mới được thêm trong bảng điều khiển của Firebase.
Trong bảng điều khiển Cơ sở dữ liệu Firestore của bảng điều khiển Firebase, bạn sẽ thấy tập hợp guestbook
cùng với thông báo mới thêm. Nếu bạn tiếp tục gửi tin nhắn, bộ sưu tập sổ lưu bút của bạn sẽ chứa nhiều tài liệu, chẳng hạn như:
bảng điều khiển của Firebase
8. Đọc tin nhắn
Đồng bộ hoá thư
Thật tuyệt khi khách có thể viết tin nhắn vào cơ sở dữ liệu, nhưng họ chưa thể xem tin nhắn trong ứng dụng.
Để hiển thị thông báo, bạn cần thêm các trình nghe kích hoạt khi dữ liệu thay đổi, sau đó tạo một phần tử trên giao diện người dùng hiển thị thông báo mới.
Bạn sẽ thêm mã để theo dõi các thông báo mới được thêm vào ứng dụng. Trước tiên, hãy thêm một phần vào HTML để hiển thị thông báo:
- Trong StackBlitz, hãy chuyển đến tệp
index.html
. - Trong
guestbook-container
, hãy thêm một mục mới có mã nhận dạng làguestbook
.<!-- ... --> <section id="guestbook-container"> <h2>Discussion</h2> <form><!-- ... --></form> <section id="guestbook"></section> </section> <!-- ... -->
Tiếp theo, hãy đăng ký trình nghe để theo dõi các thay đổi đối với dữ liệu:
- Trong StackBlitz, hãy chuyển đến tệp
index.js
. - Ở trên cùng, hãy tìm câu lệnh nhập
firebase/firestore
, sau đó thêmquery
,orderBy
vàonSnapshot
, như sau:// ... import { getFirestore, addDoc, collection, query, orderBy, onSnapshot } from 'firebase/firestore';
- Ở cuối hàm
main()
, hãy thêm mã sau để lặp lại tất cả tài liệu (thông báo trong sổ khách) trong cơ sở dữ liệu. Để tìm hiểu thêm về những gì đang diễn ra trong mã này, hãy đọc thông tin bên dưới đoạn mã.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();
Để nghe các thông báo trong cơ sở dữ liệu, bạn đã tạo một truy vấn trên một tập hợp cụ thể bằng cách sử dụng hàm collection
. Đoạn mã trên theo dõi các thay đổi trong tập hợp guestbook
, nơi lưu trữ các tin nhắn trò chuyện. Các thông báo cũng được sắp xếp theo ngày, sử dụng orderBy('timestamp', 'desc')
để hiển thị những thông báo mới nhất ở trên cùng.
Hàm onSnapshot
nhận 2 tham số: truy vấn cần sử dụng và hàm callback. Hàm gọi lại sẽ được kích hoạt khi có bất kỳ thay đổi nào đối với những tài liệu khớp với truy vấn. Điều này có thể xảy ra nếu một tin nhắn bị xoá, sửa đổi hoặc thêm. Để biết thêm thông tin, hãy xem tài liệu về Cloud Firestore.
Kiểm thử tính năng đồng bộ hoá tin nhắn
Cloud Firestore tự động và ngay lập tức đồng bộ hoá dữ liệu với những ứng dụng khách đã đăng ký cơ sở dữ liệu.
- Những thông báo mà bạn đã tạo trước đó trong cơ sở dữ liệu sẽ xuất hiện trong ứng dụng. Bạn có thể viết thông báo mới và chúng sẽ xuất hiện ngay lập tức.
- Nếu bạn mở không gian làm việc trong nhiều cửa sổ hoặc thẻ, thì các tin nhắn sẽ được đồng bộ hoá theo thời gian thực trên các thẻ.
- (Không bắt buộc) Bạn có thể thử xoá, sửa đổi hoặc thêm thông báo mới theo cách thủ công ngay trong mục Cơ sở dữ liệu của bảng điều khiển Firebase; mọi thay đổi sẽ xuất hiện trong giao diện người dùng.
Xin chúc mừng! Bạn đang đọc tài liệu Cloud Firestore trong ứng dụng của mình!
Bản xem trước ứng dụng
9. Thiết lập các quy tắc bảo mật cơ bản
Ban đầu, bạn thiết lập Cloud Firestore để sử dụng chế độ kiểm thử, tức là cơ sở dữ liệu của bạn mở cho các hoạt động đọc và ghi. Tuy nhiên, bạn chỉ nên sử dụng chế độ thử nghiệm trong giai đoạn phát triển ban đầu. Tốt nhất là bạn nên thiết lập các quy tắc bảo mật cho cơ sở dữ liệu khi phát triển ứng dụng. Bảo mật phải là một phần không thể thiếu trong cấu trúc và hành vi của ứng dụng.
Các quy tắc bảo mật cho phép bạn kiểm soát quyền truy cập vào các tài liệu và bộ sưu tập trong cơ sở dữ liệu của mình. Cú pháp quy tắc linh hoạt cho phép bạn tạo các quy tắc phù hợp với mọi thao tác ghi vào toàn bộ cơ sở dữ liệu cho đến các thao tác trên một tài liệu cụ thể.
Bạn có thể viết các quy tắc bảo mật cho Cloud Firestore trong bảng điều khiển của Firebase:
- Trong mục Tạo của bảng điều khiển Firebase, hãy nhấp vào Cơ sở dữ liệu Firestore, sau đó chọn thẻ Quy tắc (hoặc nhấp vào đây để chuyển thẳng đến thẻ Quy tắc).
- Bạn sẽ thấy các quy tắc bảo mật mặc định sau đây, với giới hạn thời gian truy cập công khai là vài tuần kể từ hôm nay.
Xác định bộ sưu tập
Trước tiên, hãy xác định những bộ sưu tập mà ứng dụng ghi dữ liệu.
- Xoá mệnh đề
match /{document=**}
hiện có để các quy tắc của bạn có dạng như sau:rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { } }
- Trong
match /databases/{database}/documents
, hãy xác định bộ sưu tập mà bạn muốn bảo mật:rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /guestbook/{entry} { // You'll add rules here in the next step. } }
Thêm quy tắc bảo mật
Vì bạn đã dùng UID xác thực làm trường trong mỗi tài liệu sổ lưu bút, nên bạn có thể lấy UID xác thực và xác minh rằng bất kỳ ai cố gắng ghi vào tài liệu đều có UID xác thực trùng khớp.
- Thêm các quy tắc đọc và ghi vào bộ quy tắc của bạn như minh hoạ dưới đây:
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; } } }
- Nhấp vào Xuất bản để triển khai các quy tắc mới.Giờ đây, đối với sổ khách, chỉ những người dùng đã đăng nhập mới có thể đọc tin nhắn (bất kỳ tin nhắn nào!), nhưng bạn chỉ có thể tạo tin nhắn bằng mã nhận dạng người dùng của mình. Chúng tôi cũng không cho phép chỉnh sửa hoặc xoá tin nhắn.
Thêm quy tắc xác thực
- Thêm quy trình xác thực dữ liệu để đảm bảo rằng tất cả các trường dự kiến đều có trong tài liệu:
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; } } }
- Nhấp vào Xuất bản để triển khai các quy tắc mới.
Đặt lại trình nghe
Vì giờ đây ứng dụng của bạn chỉ cho phép người dùng đã xác thực đăng nhập, nên bạn cần di chuyển truy vấn sổ lưu bút firestore
vào trong trình nghe Xác thực. Nếu không, lỗi về quyền sẽ xảy ra và ứng dụng sẽ bị ngắt kết nối khi người dùng đăng xuất.
- Trong StackBlitz, hãy chuyển đến tệp
index.js
. - Kéo trình nghe bộ sưu tập sổ lưu bút
onSnapshot
vào một hàm mới tên làsubscribeGuestbook
. Ngoài ra, hãy chỉ định kết quả của hàmonSnapshot
cho biếnguestbookListener
.
Trình ngheonSnapshot
của Firestore trả về một hàm huỷ đăng ký mà bạn có thể dùng để huỷ trình nghe dữ liệu nhanh sau này.// ... // 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); }); }); }
- Thêm một hàm mới bên dưới có tên là
unsubscribeGuestbook
. Kiểm tra xem biếnguestbookListener
có giá trị rỗng hay không, sau đó gọi hàm để huỷ trình nghe.// ... // Unsubscribe from guestbook updates function unsubscribeGuestbook() { if (guestbookListener != null) { guestbookListener(); guestbookListener = null; } }
Cuối cùng, hãy thêm các hàm mới vào lệnh gọi lại onAuthStateChanged
.
- Thêm
subscribeGuestbook()
ở cuốiif (user)
. - Thêm
unsubscribeGuestbook()
ở cuối câu lệnhelse
.// ... // 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. Bước bổ sung: Thực hành những gì bạn đã học
Ghi lại trạng thái hồi đáp của người tham dự
Hiện tại, ứng dụng của bạn chỉ cho phép mọi người bắt đầu trò chuyện nếu họ quan tâm đến sự kiện. Ngoài ra, cách duy nhất để bạn biết có người đang đến là khi họ đăng thông tin đó trong cuộc trò chuyện. Hãy sắp xếp và cho mọi người biết số lượng người sẽ đến.
Bạn sẽ thêm một nút bật/tắt để đăng ký những người muốn tham dự sự kiện, sau đó thu thập số lượng người tham dự.
- Trong StackBlitz, hãy chuyển đến tệp
index.html
. - Trong
guestbook-container
, hãy thêm một nhóm nút CÓ và KHÔNG, như sau:<!-- ... --> <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> <!-- ... -->
Bản xem trước ứng dụng
Tiếp theo, hãy đăng ký trình nghe cho các lượt nhấp vào nút. Nếu người dùng nhấp vào CÓ, hãy dùng UID xác thực của họ để lưu câu trả lời vào cơ sở dữ liệu.
- Trong StackBlitz, hãy chuyển đến tệp
index.js
. - Ở trên cùng, hãy tìm câu lệnh nhập
firebase/firestore
, sau đó thêmdoc
,setDoc
vàwhere
, như sau:// ... // Add the Firebase products and methods that you want to use import { getFirestore, addDoc, collection, query, orderBy, onSnapshot, doc, setDoc, where } from 'firebase/firestore';
- Ở cuối hàm
main()
, hãy thêm mã sau để theo dõi trạng thái phản hồi lời mời:async function main() { // ... // Listen to RSVP responses rsvpYes.onclick = async () => { }; rsvpNo.onclick = async () => { }; } main();
- Tiếp theo, hãy tạo một tập hợp mới tên là
attendees
, sau đó đăng ký một tham chiếu đến tài liệu nếu người dùng nhấp vào một trong hai nút Trả lời. Đặt giá trị tham chiếu đó thànhtrue
hoặcfalse
tuỳ thuộc vào nút được nhấp.
Trước tiên, đối vớirsvpYes
: Sau đó, cũng tương tự cho// ... // 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
, nhưng có giá trị là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); } };
Cập nhật Quy tắc bảo mật
Vì bạn đã thiết lập một số quy tắc, nên dữ liệu mới mà bạn đang thêm bằng các nút sẽ bị từ chối.
Cho phép thêm vào bộ sưu tập attendees
Bạn cần cập nhật các quy tắc để cho phép thêm vào bộ sưu tập attendees
.
- Đối với bộ sưu tập
attendees
, vì bạn đã sử dụng UID xác thực làm tên tài liệu, nên bạn có thể lấy UID đó và xác minh rằnguid
của người gửi giống với tài liệu mà họ đang viết. Bạn sẽ cho phép mọi người đọc danh sách người tham dự (vì không có dữ liệu riêng tư ở đó), nhưng chỉ người tạo mới có thể cập nhật danh sách này.rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { // ... // match /attendees/{userId} { allow read: if true; allow write: if request.auth.uid == userId; } } }
- Nhấp vào Xuất bản để triển khai các quy tắc mới.
Thêm quy tắc xác thực
- Thêm một số quy tắc xác thực dữ liệu để đảm bảo rằng tất cả các trường dự kiến đều có trong tài liệu:
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; } } }
- Đừng quên nhấp vào Xuất bản để triển khai các quy tắc của bạn!
(Không bắt buộc) Giờ đây, bạn có thể xem kết quả của việc nhấp vào các nút. Chuyển đến trang tổng quan Cloud Firestore trong bảng điều khiển của Firebase.
Đọc trạng thái hồi đáp
Giờ đây, bạn đã ghi lại các phản hồi, hãy xem những ai sẽ đến và phản ánh điều đó trong giao diện người dùng.
- Trong StackBlitz, hãy chuyển đến tệp
index.html
. - Trong
description-container
, hãy thêm một phần tử mới có mã nhận dạng lànumber-attending
.<!-- ... --> <section id="description-container"> <!-- ... --> <p id="number-attending"></p> </section> <!-- ... -->
Tiếp theo, hãy đăng ký trình nghe cho bộ sưu tập attendees
và đếm số câu trả lời YES:
- Trong StackBlitz, hãy chuyển đến tệp
index.js
. - Ở cuối hàm
main()
, hãy thêm mã sau để theo dõi trạng thái RSVP và số lượt nhấp vào CÓ.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();
Cuối cùng, hãy làm nổi bật nút tương ứng với trạng thái hiện tại.
- Tạo một hàm kiểm tra xem UID xác thực hiện tại có mục nhập nào trong bộ sưu tập
attendees
hay không, sau đó đặt lớp nút thànhclicked
.// ... // 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'; } } }); }
- Ngoài ra, hãy tạo một hàm để huỷ đăng ký. Tham số này sẽ được dùng khi người dùng đăng xuất.
// ... function unsubscribeCurrentRSVP() { if (rsvpListener != null) { rsvpListener(); rsvpListener = null; } rsvpYes.className = ''; rsvpNo.className = ''; }
- Gọi các hàm từ trình nghe Xác thực.
// ... // 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(); } });
- Hãy thử đăng nhập với tư cách nhiều người dùng và xem số lượt nhấp vào nút CÓ tăng lên với mỗi lượt nhấp bổ sung.
Bản xem trước ứng dụng
11. Xin chúc mừng!
Bạn đã sử dụng Firebase để tạo một ứng dụng web tương tác theo thời gian thực!
Nội dung đã đề cập
- Xác thực Firebase
- FirebaseUI
- Cloud Firestore
- Quy tắc bảo mật của Firebase
Các bước tiếp theo
- Bạn muốn tìm hiểu thêm về quy trình làm việc của nhà phát triển Firebase? Hãy xem lớp học lập trình về trình mô phỏng Firebase để tìm hiểu cách kiểm thử và chạy ứng dụng hoàn toàn cục bộ.
- Bạn muốn tìm hiểu thêm về các sản phẩm khác của Firebase? Có thể bạn muốn lưu trữ các tệp hình ảnh mà người dùng tải lên? Hoặc gửi thông báo cho người dùng? Hãy xem Lớp học lập trình web của Firebase để biết một lớp học lập trình đi sâu hơn vào nhiều sản phẩm khác của Firebase dành cho web.
- Bạn muốn tìm hiểu thêm về Cloud Firestore? Có thể bạn muốn tìm hiểu về bộ sưu tập con và giao dịch? Hãy truy cập vào lớp học lập trình web Cloud Firestore để xem một lớp học lập trình chuyên sâu hơn về Cloud Firestore. Hoặc xem loạt video này trên YouTube để tìm hiểu về Cloud Firestore!
Tìm hiểu thêm
- Trang web của Firebase: firebase.google.com
- Kênh YouTube của Firebase
Kết quả thế nào?
Chúng tôi rất mong nhận được ý kiến phản hồi của bạn! Vui lòng điền vào một biểu mẫu (rất) ngắn tại đây.