该帖子系列已在 NgateSystems.com 上建立索引。您还可以在那里找到超级有用的关键字搜索工具。
最后评论:24 年 11 月
大多数网络应用程序的存在纯粹是为了创建和访问共享信息。考虑一下亚马逊的 https://www.amazon.co.uk/ 网站。该系统的基本目的是让您浏览产品详细信息的集中集合、下订单并监控交付进度。为了实现这一目标,亚马逊必须:
这篇文章是关于用于实现这些目标的“数据库”技术。
警告 - 这是一篇长帖子,因为 Svelte 中的数据库读写会无情地吸引您使用 SvelteKit 的客户端-服务器架构。以前,您的代码仅在 Web 浏览器中“客户端”运行。现在,您还将在由 npm run dev 启动的本地服务器上运行代码。这会产生后果...
我已经研究过分割帖子的方法,但它们不起作用。更糟糕的是,您将使用的 Javascript 包含许多新功能。所以,我很抱歉 - 你只能忍耐了。
但也要往好的方面看。一旦你经历了这一切,事情就会开始变得更容易。慢慢来。如果您觉得我没有解释清楚,请使用 chatGPT。当您需要有关 JavaScript 语法的建议时,您会发现该机器人特别有用。放松。这会很有趣!
在网络上存储共享数据的方法有无数种。本系列文章使用 Google 的 Firestore 系统,因为它适合初学者。它需要最少的设置,并且非常适合 Svelte Web 应用程序的结构。
您需要执行四个初始步骤:
Firebase 是 Google 的总称,涵盖了许多不同的服务,您可以使用这些服务在网络上安装简单的项目。给定帐户的服务通过 Google 的“Firebase 控制台”(网址为 https://console.firebase.google.com/)进行管理。它们包括允许您将文件上传到 Google Cloud 的“存储”服务和“Firestore 数据库”服务。数据库与文件的不同之处在于它具有可配置的结构。它使您能够访问和更新已配置数据集的离散元素。
如果您有 Gmail 地址,那么您就已经受到保护,因为这会自动算作 Google 帐户。如果没有,请按照创建 Google 帐户中的说明获取一个。
启动 Google Firebase 控制台并使用您的 Google 帐户登录(请注意,如果您使用此帐户登录 Gmail,则您也已经登录 Firebase 控制台)。现在单击“创建项目”框来启动该过程。
Google 会要求您为您的项目提供一个名称(我建议您使用您在 VSCode 中使用的项目名称),并会提出一个扩展,使其成为 Firebase 世界中唯一的“项目标识符”。例如,本系列文章中使用的我的版本的“Svelte-dev”项目在 Google 中被称为“Svelte-dev-afbaf”。
顺便说一句,由于项目标识符最终将构成您的网络应用程序的默认实时 URL 的一部分,并且由于 Google 允许您编辑其最初的“唯一性扩展”提案,因此您可能会尝试更改此设置去做一些有意义的事情。不过,我建议你忘记这个想法。首先,您会发现很难选择适合双方的标识符。其次,根据我的经验,这些“默认网址”从未被 Google 索引过。以最低成本购买并在上线时链接到默认 URL 的“自定义 URL”是迄今为止获得令人难忘的 URL 的最佳方式。
现在点击“继续”即可显示“Google Analytics”注册页面。您可以在此处安全地忽略它,因为它仅与实时应用程序的性能问题相关。使用滑块拒绝它,然后单击“创建项目”按钮继续。
当 Google 注册您的项目时,灯光现在变暗了一点。最后,一旦您再点击一个“继续”按钮,您就会发现自己位于项目的 Firebase 控制台窗口中。以下是“svelte-dev”项目的 Firestore 选项卡的屏幕截图:
值得给自己一点时间来熟悉这个页面,因为它有点复杂。基本结构由左侧的“工具菜单”组成,它确定右侧主面板中显示的内容。问题在于菜单是“自适应”的,并维护一个“项目快捷方式”部分来记住您去过的地方。因此,每次打开控制台时,菜单看起来都不同!然而,一旦掌握了这个功能,事情就会进展顺利。请注意,完整的工具集隐藏在其父“产品类别”菜单项的“构建”、“运行”和“分析”子菜单中。 “构建”套装包含您目前需要的一切。
在继续操作之前,请注意以下事项:
Firebase 需要知道您的网络应用程序的名称:
从工具菜单的“Build”堆栈中选择“Firestore Database”以获得如下所示的 Firebase 控制台视图:
单击“创建数据库”按钮后,控制台将要求您:
设置您的数据库“名称和位置”。 “名称”是数据库的标识符,仅当您计划在项目中创建多个不同的数据库时才相关。现在将其留空,以便 Google 使用其“默认”设置。 “位置”指定数据库的物理位置。此处提供的选项下拉列表可能是您对 Google Cloud 服务规模的第一印象。其服务器场遍布全球。您可能需要选择靠近您所在位置的服务器。例如,我通常使用“europe-west2 : Heathro”,因为我住在英国。 Google Cloud 控制台中其他页面允许您指定性能和可用性特征,但您现在不需要查看这些。
使用“规则”保护您的数据库。这里的屏幕为您提供了设置初始“生产”和“测试”“规则”之间的选择。当然,这只有在你首先知道“规则”是什么的情况下才有意义——而现在不是我解释它们的合适时机。除非您更了解,否则我希望您检查此处的“测试模式”选项。请放心,稍后当我谈论“授权”时我会回到这个话题(天哪,还有很多东西要谈!)。
完成这两个阶段后,Cloud Firestore 页面将在 Firebase 控制台中打开。现在怎么办?
本节旨在回答以下问题:
就我们的直接目的而言,数据库是一组表,其中包含命名数据“字段”的值行。因此,例如,“客户订单”数据库可能包含
重要的是这样的安排结构化数据内容的命名和格式具有一致的标准
在 Firestore 中,表称为“集合”,其中的行称为“文档”。集合中存储的文档并不都需要具有相同的字段,但字段名称和内容应在整个集合中遵循一致的模式。
Firestore 文档的一个重要特征是它应该有一个唯一的标识符或“密钥”。有时,每个文档中都会有一个字段,例如“电子邮件地址”,您可以使用它来提供“自然”唯一密钥。如果没有,Firestore 可能会被要求自动创建一个人工密钥。
数据库设计可能是系统开发中最具挑战性的部分,我将再次回避这一点,因为只有当您拥有一些实践经验时,所涉及的问题才会变得清晰。不过,如果您有时间,您会发现查看 Cloud Firestore 数据模型页面很有用。
在这篇文章中,我计划向您展示如何在默认 Firestore 数据库中创建单个产品集合。这将包含简单的文档,其中包含产品编号字段以及 Firestore 自动生成的密钥。
在 Firebase 控制台的 Firestore 页面上,单击“开始收集”按钮,然后在现在出现的弹出窗口的“集合 ID”字段中输入名称“产品”。
现在使用数据输入页面创建一个测试产品文档,其中包含数值为“1”的“productNumber”字段和文本值为“Product 1”的“productDetails”字段。
现在,首先单击“自动 ID”按钮,然后“保存”来签署文档,控制台现在应如下所示:
如果您想添加更多文档,此时您可以单击“添加文档”,但在本例中没有必要 - 您只需要一个文档来演示您的 Web 应用程序读取它的能力。
您现在已经完成了,但请注意,控制台的“面板视图”允许您编辑或删除刚刚创建的文档。如果您的情况一团糟,您甚至可以删除整个集合并重新开始。
事情开始变得真的有趣了!
Google 提供了一个 Javascript 函数库,可让您读取和写入 Firestore 文档。此类库称为“API”(应用程序接口)。看一下下面的代码,它显示了如何使用 firebase/firestore 库来读取 svelte-dev 产品集合中的所有文档:
import { collection, query, getDocs, orderBy } from "firebase/firestore"; import { initializeApp } from "firebase/app"; import { getFirestore } from "firebase/firestore"; const firebaseConfig = { apiKey: "AIzaSyCE933 ... klfhFdwQg1IF1pWaR1iE", authDomain: "svelte-dev-afbaf.firebaseapp.com", projectId: "svelte-dev-afbaf", storageBucket: "svelte-devt-afbaf.appspot.com", messagingSenderId: "1027 ... 85697", appId: "1:1027546585697:web:27002bf ..... b0f088e820", }; const firebaseApp = initializeApp(firebaseConfig); const db = getFirestore(firebaseApp); const productsCollRef = collection(db, "products"); const productsQuery = query(productsCollRef, orderBy("productNumber", "asc")); const productsSnapshot = await getDocs(productsQuery); let currentProducts = []; productsSnapshot.forEach((product) => { currentProducts.push({productNumber: product.data().productNumber}); }); return { products: currentProducts } // accessed in +page.svelte as data.products
重点关注以 const productsCollRef = collection(db, "products"); 开头的部分。这使用 Firestore API 调用将产品集合中所有文档的排序副本加载到 State currentProducts 变量中。
首先,从 Firestore 客户端 API 库中提取的集合和查询函数用于将 Firebase 指向产品集合并定义要在其上运行的查询。然后通过 getDocs API 调用启动查询。
我不会尝试描述这一系列 Firestore API 调用的机制。将它们视为一段“样板代码” - 代码 - 那种您编写一次,然后简单复制的东西。由于您会发现需要一个完整的模板库来涵盖 Firestore“读取”、“更新”和“删除”操作的全部数组,因此您可能会发现查看 Post 10.1 - Firestore CRUD 命令模板很有用。如果您想查看 Google 自己的 API 描述,您可以在第 10.1 篇文章的末尾找到这些内容的链接。
这里的“CRUD”是“创建”、“读取”、“更新”和“删除”的缩写。
getDocs 结果作为文档数组返回,通常称为“快照”。但请注意,getDocs 函数调用前面有一个await 关键字。
这里需要await关键字,因为默认情况下,在Javascript中,引用外部数据源的指令可能需要不可预测的时间才能完成异步处理。 “await”关键字本质上(尽管这是一个粗略的简化)使您能够覆盖这种安排。当您有更多时间时,您可能会发现查看 Javascript fetch() API 和“await”关键字的简单指南很有用
但是现在,回到上面的代码片段,看看以 const firebaseConfig 语句开头的部分。
firebaseConfig 声明初始化一个对象,其中包含将 Web 应用连接到特定 Firebase 项目所需的配置详细信息。它包括 Firebase 用于定位和验证您的应用程序的各种密钥和标识符。您可以在 Firebase 控制台的“项目概览/项目设置”中找到您的特定 Web 应用的设置。下面代码示例中的 firebaseConfig 设置已被“混淆”,因为它们是 我的 项目所特有的,并且不能轻易传递(稍后将详细介绍这一点)。尝试下面的示例代码时,您需要从您自己的项目中复制 firebaseConfig 设置。
初始化 firebaseConfig 后,Web 应用程序可以初始化查询的 const productsCollRef = collection(db, "products"); 所需的 db 变量。声明:
import { collection, query, getDocs, orderBy } from "firebase/firestore"; import { initializeApp } from "firebase/app"; import { getFirestore } from "firebase/firestore"; const firebaseConfig = { apiKey: "AIzaSyCE933 ... klfhFdwQg1IF1pWaR1iE", authDomain: "svelte-dev-afbaf.firebaseapp.com", projectId: "svelte-dev-afbaf", storageBucket: "svelte-devt-afbaf.appspot.com", messagingSenderId: "1027 ... 85697", appId: "1:1027546585697:web:27002bf ..... b0f088e820", }; const firebaseApp = initializeApp(firebaseConfig); const db = getFirestore(firebaseApp); const productsCollRef = collection(db, "products"); const productsQuery = query(productsCollRef, orderBy("productNumber", "asc")); const productsSnapshot = await getDocs(productsQuery); let currentProducts = []; productsSnapshot.forEach((product) => { currentProducts.push({productNumber: product.data().productNumber}); }); return { products: currentProducts } // accessed in +page.svelte as data.products
最后,您可能想知道这些 API 函数从何而来。答案是它们是通过代码块顶部的三个语句从项目中的位置导入的:
const firebaseApp = initializeApp(firebaseConfig); const db = getFirestore(firebaseApp);
这里正在访问“模块化库”来为您的代码提供函数。从父模块中提取命名函数(例如集合),以满足代码中稍后所需的引用。
但这又引出了一个问题“模块化库首先如何进入我的项目?”答案当然是你必须把它们放在那里,而你用来执行此操作的工具是忠实的旧 npm。
返回 VSCode svelte-test 终端会话(如有必要,通过几次 ctrl-C 按键终止开发服务器)并运行以下指令'
import { collection, query, getDocs, orderBy } from "firebase/firestore"; import { initializeApp } from "firebase/app"; import { getFirestore } from "firebase/firestore"; const firebaseConfig = { apiKey: "AIzaSyCE933 ... klfhFdwQg1IF1pWaR1iE", authDomain: "svelte-dev-afbaf.firebaseapp.com", projectId: "svelte-dev-afbaf", storageBucket: "svelte-devt-afbaf.appspot.com", messagingSenderId: "1027 ... 85697", appId: "1:1027546585697:web:27002bf ..... b0f088e820", }; const firebaseApp = initializeApp(firebaseConfig); const db = getFirestore(firebaseApp); const productsCollRef = collection(db, "products"); const productsQuery = query(productsCollRef, orderBy("productNumber", "asc")); const productsSnapshot = await getDocs(productsQuery); let currentProducts = []; productsSnapshot.forEach((product) => { currentProducts.push({productNumber: product.data().productNumber}); }); return { products: currentProducts } // accessed in +page.svelte as data.products
一两分钟后(安装涉及大量下载),您将准备好运行下载 Firestore 数据库集合的代码。但是,您仍然不知道如何将其嵌入到 Svelte Web 应用程序中。那么,进入下一个问题...
这是一个漫长的过程,但是,坚持下去,你就快完成了。
目前,在<script>中在 src/routes/ page.svelte 文件的部分,您有以下语句:<br> </script>
const firebaseApp = initializeApp(firebaseConfig); const db = getFirestore(firebaseApp);
如您所知,这将您的产品字段声明为状态变量并将其初始化为空数组。您现在要做的是将“空”替换为 Firestore 产品集合的内容。
不幸的是,正如您所看到的,这涉及异步操作。这让事情变得有些复杂,因为 Svelte 不希望任何东西减慢页面的初始加载速度 - 它很高兴看到稍后添加的信息,但是,用户的第一印象应该是即时响应。 Svelte 有一个将初始数据加载到 page.svelte 文件中的标准安排。事情是这样的:
首先,创建一个新的 src/routes/ page.server.js 文件,将所有异步代码包装在 load() 函数(强制名称)内,并将其结果作为对象返回。
这是代码
import { collection, query, getDocs, orderBy } from "firebase/firestore"; import { initializeApp } from "firebase/app"; import { getFirestore } from "firebase/firestore";
上面的 load 函数返回一个具有单个 products 属性的对象,其值是由 Firestore API 调用构造的 currentProducts 数组。
这一切都很好,但是如何将其传达给 page.svelte 中的产品状态变量呢?
第一步是将新数据(强制名称)状态变量广告为 page.svelte 的 prop(“property”的缩写),您可以通过使用导出关键字声明它来实现此目的,因此:
npm install firebase
在您到达本系列的第 3.1 篇文章并了解“组件”之前,本系列不会介绍 Props。现在,将您的 page.svelte 文件视为一个以数据作为参数的函数。
当您现在运行 page.svelte 文件时,SvelteKit 框架会看到带有保留数据关键字的导出 let 数据声明,并认为:“啊,我需要运行与此页面关联的 load() 函数”。产品数据及时返回到 page.svelte 的 data 属性中,现在,由于这是一个反应变量,因此页面被刷新。
要使现有的“模板”代码适用于新的安排,您所需要做的就是用 data.products 替换产品引用
page.server.js 文件是您在 Svelte 中第一次看到的“服务器端”代码 - 即在服务器中运行的代码。到目前为止,您所看到的所有 page.svelte 代码都在浏览器中“客户端”运行。相比之下,page.server.js 文件要么在 npm run dev 启动的本地服务器中运行,要么在部署后在 App Engine 服务器的 Node.js 环境中运行。服务器端代码比客户端代码运行速度更快并且安全。唯一可以查看或更改它的人是您 - 它的所有者。
以下是 Post 2.2 中 page.svelte 文件修改版本的完整代码:
import { collection, query, getDocs, orderBy } from "firebase/firestore"; import { initializeApp } from "firebase/app"; import { getFirestore } from "firebase/firestore"; const firebaseConfig = { apiKey: "AIzaSyCE933 ... klfhFdwQg1IF1pWaR1iE", authDomain: "svelte-dev-afbaf.firebaseapp.com", projectId: "svelte-dev-afbaf", storageBucket: "svelte-devt-afbaf.appspot.com", messagingSenderId: "1027 ... 85697", appId: "1:1027546585697:web:27002bf ..... b0f088e820", }; const firebaseApp = initializeApp(firebaseConfig); const db = getFirestore(firebaseApp); const productsCollRef = collection(db, "products"); const productsQuery = query(productsCollRef, orderBy("productNumber", "asc")); const productsSnapshot = await getDocs(productsQuery); let currentProducts = []; productsSnapshot.forEach((product) => { currentProducts.push({productNumber: product.data().productNumber}); }); return { products: currentProducts } // accessed in +page.svelte as data.products
此代码应该位于哪里?目前,“添加另一个产品”
以上是NgSysV.使用 Googles Firestore 创建一个简单的 Svelte 信息系统的详细内容。更多信息请关注PHP中文网其他相关文章!