Minimus云存储揭秘:Firestore天气应用按用户隔离城市列表的完整教程
【免费下载链接】minimus🌦️ A fully featured production ready Angular weather app (tutorial)项目地址: https://gitcode.com/gh_mirrors/mi/minimus
Minimus 是一款功能完整、可直接上生产的 Angular 天气应用(weather app),它的核心玩法是"关注你关心的城市"——而这份城市列表并不存在浏览器本地,而是存放在云端 Firestore 数据库中,按用户(uid)隔离存储,登录任何设备都能同步。这篇文章将带你快速看懂它的设计思路与实现细节,新手也能轻松上手。
🌐 什么是 Minimus 天气应用?
Minimus 用 Angular 搭建了一个完整的生产级天气应用,包含这几大能力:
| 能力 | 说明 |
|---|---|
| 天气查询 | 接入天气 API,展示城市温度与状态 |
| 城市关注 | 从各国首都列表中挑选城市并"添加"到个人列表 |
| 用户体系 | Firebase Auth 提供注册 / 登录,会话状态由前端守卫保护 |
| 云端存储 | Firestore 按用户隔离保存城市列表,跨设备同步 |
| PWA 支持 | Service Worker 注册,支持离线与安装 |
模块组织清晰,与云存储直接相关的目录如下:
- 数据服务:src/app/services/fb/fb.service.ts
- 城市列表页:src/app/pages/home/home.component.ts
- 添加城市页:src/app/pages/add/add.component.ts
- 路由与守卫:src/app/app-routing.module.ts、src/app/guards/app.guard.ts
🔗 整体架构:城市列表数据流全景
一次"关注城市"操作的完整数据流非常简单:
- 注册 / 登录:登录组件 和 注册组件 调用
FbService的signin/signup,背后是 Firebase 认证; - 登录成功:跳转首页,
HomeComponent在ngOnInit中调用fb.getCities(),用async管道把订阅到的城市渲染成一张张天气卡片; - 添加城市:
AddComponent调用fb.addCity(),把{name, added}写入 Firestore; - 云端落地:所有读写都发生在
FbService内部,页面组件完全不感知存储细节——服务层是唯一接触 Firestore 的地方,这是它值得学习的架构习惯。
Firestore 按用户隔离存储城市列表
🏛️ 设计核心:用 uid 作为文档路径实现按用户隔离
这是全文最关键的一点。Firestore 采用"集合 - 文档"的分层结构,Minimus 的做法是:把用户的 uid 直接当作顶层文档路径,每个用户天然拥有一个独立的数据空间:
Firestore └── {uid: "aB3x..."} ← 用户A 的专属文档(路径即 uid) ├── Rome → { name: "Rome", added: "2026-08-23..." } └── Tokyo → { name: "Tokyo", added: "2026-08-23..." } └── {uid: "Kd9y..."} ← 用户B 的专属文档,与A完全隔离 └── Paris → { name: "Paris", added: "..." }为什么这样设计好?
- 零配置的权限隔离:不用手工建"users"集合再嵌套子集合,路径本身就是租户边界,用户 A 的查询永远只落在自己的文档里;
- 读写路径最短:读取整份列表是一次
read(uid),写入一座城市是一次write(uid/name),各只需一条路径; - 天然覆盖更新:城市名作为子键再次写入时直接覆盖,天然支持"取消关注再重新关注"。
在 fb.service.ts 中,核心实现只有两个方法:
getCities() { return this.auth.uid().pipe(switchMap((uid) => { return this.fs.read(`${uid}`); })); } addCity(name: string) { return this.auth.uid().pipe(switchMap((uid) => { return this.fs.write(`${uid}/${name}`, {name, added: new Date()}) .pipe(first()); }), first()); }配合响应式操作符,两行思路就能说清:
auth.uid()是一个流,登录状态就绪后才发出 uid,未登录时根本不会发起任何读请求;switchMap把"拿到 uid"无缝衔接成"按 uid 读 / 写",形成认证 → 存储的自动流水线;first()让写操作在拿到首次结果后即完成订阅,避免多余往返。
🚦 路由守卫:云存储的双重门卫
再好的隔离也需要前端兜底。Minimus 用两个极简守卫在路由层完成"谁能进哪扇门"(见 app-routing.module.ts):
| 页面 | 守卫 | 行为 |
|---|---|---|
| 首页 / 详情 / 添加 | AppGuard | 未登录 → 强制跳/login |
| 登录 / 注册 | AuthGuard | 已登录 → 踢回首页,避免重复登录 |
两个守卫都只依赖FbService.isAuth()这一个方法,逻辑清晰:云数据区需要门票,门票区不欢迎已有门票的人。这对新手是很好的守卫设计范本——守卫只做判断与跳转,不做业务。
⚙️ 配置指南:Firebase 密钥放在哪里
项目没有把密钥写死在组件里,而是遵循 Angular 的环境文件约定:
- 开发环境:src/environments/environment.ts 中预留了
apiKey、authDomain、projectId等字段占位; - 生产环境:src/environments/environment.prod.ts 由构建时的
fileReplacements自动替换。
应用启动时,在 app.module.ts 中通过AngularFireLite.forRoot(environment.config)一次性完成 Firebase 初始化——认证与 Firestore 客户端(AngularFireLiteAuth、AngularFireLiteFirestore)由此注入到FbService中。
💡 小贴士:仓库里的环境文件默认是空占位符,动手前请填入你自己 Firebase 项目的配置,这是教程型仓库的常见做法。
✅ 新手可复用的设计清单
从 Minimus 的 Firestore 城市列表设计中,可以带走这几条经验:
- 按 uid 建文档路径——用登录态天然完成多租户隔离,不依赖复杂权限规则起步;
- 服务层收敛存储细节——组件只调业务方法(
getCities/addCity),不直接碰数据库; - 认证流驱动数据流——
uid()+switchMap让"登录后才读数据"成为代码结构本身,而非运行时 if 判断; - 路由守卫分层——
AppGuard保护数据页,AuthGuard反制已登录用户,两个小文件覆盖全站安全; - 环境文件管理密钥——开发与生产配置分离,密钥不进组件代码。
🚀 快速上手:动手跑一遍
如果你已经配置好 Angular CLI,可以克隆仓库并填入 Firebase 配置后启动:
git clone https://gitcode.com/gh_mirrors/mi/minimus cd minimus npm install npm start打开首页注册一个账号,再添加一座城市,然后换一个浏览器重新登录——你会看到同一份城市列表出现在两个环境里。那一刻,你就真正理解了"Firestore 按用户隔离存储"的完整闭环。🎉
【免费下载链接】minimus🌦️ A fully featured production ready Angular weather app (tutorial)项目地址: https://gitcode.com/gh_mirrors/mi/minimus
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考