如何用Materialize、JS与Firebase v9 FireStore实现收藏按钮功能
实现Materialize卡片收藏到Favorites页面(结合Firebase v9 FireStore)
下面分步骤完成收藏功能,涵盖数据存储、页面跳转和收藏列表渲染:
一、Firebase v9 初始化配置
创建单独的firebase.js文件,配置Firebase并导出所需服务(使用v9模块化语法):
// firebase.js import { initializeApp } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-app.js"; import { getFirestore, collection, addDoc, getDocs, deleteDoc, doc } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-firestore.js"; // 替换为你的Firebase项目配置 const firebaseConfig = { apiKey: "YOUR_API_KEY", authDomain: "YOUR_AUTH_DOMAIN", projectId: "YOUR_PROJECT_ID", storageBucket: "YOUR_STORAGE_BUCKET", messagingSenderId: "YOUR_SENDER_ID", appId: "YOUR_APP_ID" }; const app = initializeApp(firebaseConfig); const db = getFirestore(app); export { db, collection, addDoc, getDocs, deleteDoc, doc };
在index.html和Favorites.html的</body>前引入该脚本:
<script type="module" src="firebase.js"></script>
二、修改index.html卡片结构并添加收藏逻辑
首先给卡片添加外层容器,方便定位数据:
<!-- 给卡片添加外层容器 --> <div class="recipe-card card"> <div class="recipe-img"> <img src="coffee.jpg" alt="a cup of coffee."> <span class="category-name">Mine</span> </div> <div class="recipe-content"> <a href="#" class="right btn-floating grey"><i class="material-icons">delete_outline</i></a> <h2>Americano <a href="#" class="right favorite-btn btn-floating red pulse"> <i class="material-icons">favorite</i> </a> </h2> <p>Lorem, ipsum dolor sit amet consectetur adipisicing elit...</p> </div> </div>
创建index.js脚本,处理收藏按钮点击事件:
// index.js import { db, collection, addDoc } from "./firebase.js"; // 获取所有收藏按钮 const favoriteBtns = document.querySelectorAll('.favorite-btn'); favoriteBtns.forEach(btn => { btn.addEventListener('click', async (e) => { e.preventDefault(); // 阻止默认跳转行为 // 定位当前卡片容器 const card = btn.closest('.recipe-card'); // 提取卡片核心数据 const recipeData = { title: card.querySelector('h2').textContent.trim(), image: card.querySelector('.recipe-img img').src, category: card.querySelector('.category-name').textContent, description: card.querySelector('p').textContent.trim() }; try { // 将数据存入Firestore的favorites集合 await addDoc(collection(db, "favorites"), recipeData); // 用Materialize Toast提示收藏成功 M.toast({html: '已添加到收藏'}); // 延迟1秒跳转到收藏页面 setTimeout(() => { window.location.href = 'Favorites.html'; }, 1000); } catch (e) { console.error('添加收藏失败:', e); M.toast({html: '收藏失败,请重试'}); } }); });
在index.html中引入该脚本:
<script type="module" src="index.js"></script> <!-- 别忘了引入Materialize JS --> <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
三、在Favorites.html渲染收藏列表
先编写Favorites.html的基础结构:
<!DOCTYPE html> <html> <head> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css"> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> </head> <body> <div class="container"> <h1>我的收藏</h1> <div id="favorites-container" class="row"></div> </div> <script type="module" src="firebase.js"></script> <script type="module" src="favorites.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script> </body> </html>
创建favorites.js脚本,读取Firestore数据并渲染卡片:
// favorites.js import { db, collection, getDocs, deleteDoc, doc } from "./firebase.js"; const favoritesContainer = document.getElementById('favorites-container'); // 渲染收藏列表 async function renderFavorites() { try { const querySnapshot = await getDocs(collection(db, "favorites")); favoritesContainer.innerHTML = ''; // 清空容器 querySnapshot.forEach((doc) => { const recipe = doc.data(); // 创建Materialize卡片元素 const cardCol = document.createElement('div'); cardCol.className = 'col s12 m6 l4'; // 响应式布局 cardCol.innerHTML = ` <div class="recipe-card card"> <div class="recipe-img"> <img src="${recipe.image}" alt="${recipe.title}"> <span class="category-name">${recipe.category}</span> </div> <div class="recipe-content"> <a href="#" class="right btn-floating grey" data-id="${doc.id}"> <i class="material-icons">delete_outline</i> </a> <h2>${recipe.title}</h2> <p>${recipe.description}</p> </div> </div> `; favoritesContainer.appendChild(cardCol); // 添加删除收藏功能 const deleteBtn = cardCol.querySelector('.btn-floating.grey'); deleteBtn.addEventListener('click', async (e) => { e.preventDefault(); const docId = deleteBtn.getAttribute('data-id'); await deleteDoc(doc(db, "favorites", docId)); M.toast({html: '已移除收藏'}); renderFavorites(); // 重新渲染列表 }); }); } catch (e) { console.error('获取收藏失败:', e); favoritesContainer.innerHTML = '<p>加载收藏失败,请稍后重试</p>'; } } // 页面加载完成后渲染列表 document.addEventListener('DOMContentLoaded', renderFavorites);
四、关键注意事项
- Firestore规则设置:开发阶段可将数据库规则设为测试模式,生产环境需结合Firebase Auth限制用户仅能读写自己的收藏:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /favorites/{doc} { allow read, write: if request.auth != null; } } } - 选择器匹配:确保JS中的DOM选择器与你的HTML结构完全一致,避免数据提取失败。
- Materialize组件:Toast等组件会自动初始化,若使用其他组件(如模态框)需手动调用
M.XXX.init()方法。
内容的提问来源于stack exchange,提问作者Kristen davis
相关产品推荐
相关产品推荐

