当前位置: 首页 > news >正文

Minimus云存储揭秘:Firestore天气应用按用户隔离城市列表的完整教程

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

🔗 整体架构:城市列表数据流全景

一次"关注城市"操作的完整数据流非常简单:

  1. 注册 / 登录:登录组件 和 注册组件 调用FbServicesignin/signup,背后是 Firebase 认证;
  2. 登录成功:跳转首页,HomeComponentngOnInit中调用fb.getCities(),用async管道把订阅到的城市渲染成一张张天气卡片;
  3. 添加城市AddComponent调用fb.addCity(),把{name, added}写入 Firestore;
  4. 云端落地:所有读写都发生在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 中预留了apiKeyauthDomainprojectId等字段占位;
  • 生产环境:src/environments/environment.prod.ts 由构建时的fileReplacements自动替换。

应用启动时,在 app.module.ts 中通过AngularFireLite.forRoot(environment.config)一次性完成 Firebase 初始化——认证与 Firestore 客户端(AngularFireLiteAuthAngularFireLiteFirestore)由此注入到FbService中。

💡 小贴士:仓库里的环境文件默认是空占位符,动手前请填入你自己 Firebase 项目的配置,这是教程型仓库的常见做法。

✅ 新手可复用的设计清单

从 Minimus 的 Firestore 城市列表设计中,可以带走这几条经验:

  1. 按 uid 建文档路径——用登录态天然完成多租户隔离,不依赖复杂权限规则起步;
  2. 服务层收敛存储细节——组件只调业务方法(getCities/addCity),不直接碰数据库;
  3. 认证流驱动数据流——uid()+switchMap让"登录后才读数据"成为代码结构本身,而非运行时 if 判断;
  4. 路由守卫分层——AppGuard保护数据页,AuthGuard反制已登录用户,两个小文件覆盖全站安全;
  5. 环境文件管理密钥——开发与生产配置分离,密钥不进组件代码。

🚀 快速上手:动手跑一遍

如果你已经配置好 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),仅供参考

http://www.cnnetsun.cn/news/4189643.html

相关文章:

  • 美赛D题深度复盘:如何将团队合作量化建模与策略优化
  • 美赛B题建模实战:从沙堡持久性问题看交叉学科建模心法
  • C++函数模板深度解析:从泛型编程原理到工程实践避坑指南
  • SDC命令详解:使用set_max_transition命令进行约束
  • AI代码助手静默语义失败:成因剖析与防御实践指南
  • DeepResearch-9K:AI智能体深度研究能力的标准化评估基准
  • htop 主题定制:改 3 个开关,默认界面一眼看清谁在吃 CPU
  • AI编码代理的“自信且错误”陷阱:静默语义失败与防御策略
  • TranAD对比8大基线模型:LSTM_AD、OmniAnomaly、USAD、GDN等异常检测算法实测分析
  • 应广PMS132B单片机入门:从寄存器操作到点灯实战
  • Web智能体安全新范式:基于推理驱动的提示词注入防御实践
  • AI编码智能体如何作为测试套件审计员,发现传统测试遗漏的缺陷
  • 盘点编程题库
  • 智能体化数据系统:如何弥合语义鸿沟,避免分析工作流落地失败?
  • STM32标准库开发入门:从零搭建工程到点亮LED实战指南
  • 为什么 playground-elements 默认把沙箱放在 unpkg.com?读懂 4 条关键安全规则
  • 原生PHP网站如何实现QQ登录?
  • ATANT v1.1基准测试:系统化评估大模型记忆与长上下文能力
  • 解释一下Cookie和Session的区别及其应用场景。
  • 【学习篇】C语言数组填充值规则
  • Chrome与Edge技巧与扩展
  • CentOS/Ubuntu服务器等保整改实战:从安全基线到合规落地
  • 基于RK3588的边缘AI实战:从芯片解析到智慧场景全链路部署
  • VSCode+CMake中文乱码终极解决方案:从原理到实战
  • 深入解析C++ Vector:从动态数组到高性能容器的核心原理与实践
  • 基于OpenClaw与GLM 5.1构建免费AI Agent:本地部署与实战指南
  • 多智能体协作重塑长视频:Soap2Soap架构与实现解析
  • Java全栈工程师面试核心技术与实战指南
  • ComfyUI-LTXVideo 完整上手教程:10 分钟跑出第一条 LTX-2 视频
  • AI时代求职必备:5款降AI率工具深度评测