通过AngularFire在Angular中使用CloudFirestore

来自菜鸟教程
跳转至:导航、​搜索

Cloud Firestore 刚刚宣布作为一个新的数据库来填补 Firebase 实时数据库可能不是最佳工具的空白。 Cloud Firestore 是一个基于文档的 NoSQL 数据库。 数据库的根目录是集合(例如:todosusersfiles),集合只能包含文档。 文档包含键值对,并且可以包含它们自己的集合,称为 subcollections。 因此,与传统 Firebase 实时数据库提供的平面 JSON 树相比,这使得构建具有更复杂层次需求的应用程序变得更加容易。

在这里,我们将介绍在 Angular 2+ 项目中使用与 Cloud Firestore 交互的基础知识。 您需要有一个 Firebase 帐户 并启用新数据库。

设置

首先,安装所需的 Firebase 软件包( 火力基地 & 角火2 ) 到您的 Angular 项目中:

$ yarn add firebase angularfire2

# or, using npm:
$ npm install firebase angularfire2

然后将 AngularFireModuleAngularFirestoreModule 添加到您的应用模块:

app.module.tsc

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AngularFireModule } from 'angularfire2';
import { AngularFirestoreModule } from 'angularfire2/firestore';
import { environment } from '../environments/environment';
import { AppComponent } from './app.component';

请注意,我们在 AngularFirestoreModule 上调用 enablePersistence 方法来自动启用 Chrome、Safari 和 Firefox 上的本地缓存,这将允许应用在离线时保持可用。


有了这个,您的 Firebase 应用程序配置将位于 enviroment.ts 文件中,如下所示:

/环境/环境.ts

export const environment = {
  production: false,
  firebase: {
    apiKey: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
    authDomain: 'your-project-id.firebaseapp.com',
    databaseURL: 'https://your-project-id.firebaseio.com',
    projectId: 'your-project-id',
    storageBucket: 'your-project-id.appspot.com',
    messagingSenderId: 'XXXXXXXXXXXX'
  }
};

基本用法

现在我们的应用已经配置了 Firebase,我们可以开始使用数据库了。 我们将围绕包含 todos 集合和该集合中包含 descriptioncompleted 的简单 todo 应用程序的想法演示一些 CRUD 操作 字段。

首先,您需要将可注入的 AngularFirestore 注入到您的组件中:

import { Component } from '@angular/core';
import { AngularFirestore } from 'angularfire2/firestore';

@Component({ ... })
export class AppComponent {
  constructor(private afs: AngularFirestore) {
    // ...
  }
}

要访问集合,您可以使用以下内容创建对它的引用:

this.todoCollectionRef = this.afs.collection('todos'); // a ref to the todos collection

创建对集合的引用不会进行任何网络调用,并且引用不存在的集合是安全的,因为如果需要,将自动创建集合。 没有任何文档的集合也将被自动删除。


然后,您可以通过在集合引用上调用 valueChanges() 来监听集合文档的更改:

this.todo$ = this.todoCollectionRef.valueChanges();

valueChanges 方法返回集合中文档的 observable。 还有一个 snapshotChanges 方法,它还返回 id 以及关于我们文档的元数据。 阅读使用 snapshotChanges 的示例。



因此,这是我们开始的 todo 应用程序,它将从数据库中获取 todos 集合中的文档:

app.component.ts

import { Component } from '@angular/core';
import {
  AngularFirestore,
  AngularFirestoreCollection
} from 'angularfire2/firestore';

import { Observable } from 'rxjs/Observable';
export interface Todo {
  description: string;
  completed: boolean;
}
@Component({ ... })
export class AppComponent {
  todoCollectionRef: AngularFirestoreCollection<Todo>;
  todo$: Observable<Todo[]>;

我们可以像这样简单地在模板中显示我们的待办事项:

app.component.html

<ul>
  <li *ngFor="let todo of todo$ | async"
      [class.completed]="todo.completed">
    {{ todo.description }}
  </li>
</ul>

添加项目

要在集合中添加新文档,只需在集合引用上调用 add

addTodo(todoDesc: string) {
  if (todoDesc && todoDesc.trim().length) {
    this.todoCollectionRef.add({ description: todoDesc, completed: false });
  }
}

由于我们的 todo 集合引用是针对我们的 Todo 接口键入的,TypeScript 编译器将知道应该使用 add 方法传递的数据的形状。


更新和删除项目

要更新或删除集合中的文档,我们还需要文档的 id,它不会通过 valueChanges 方法返回。 我们将稍微改变我们的实现以使用 snapshotChanges 方法,并且还包括每个待办事项文档的 id

app.component.ts

import { Component } from '@angular/core';
import {
  AngularFirestore,
  AngularFirestoreCollection
} from 'angularfire2/firestore';

import { Observable } from 'rxjs/Observable';
export interface Todo {
  id?: string;
  description: string;
  completed: boolean;
}
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  todoCollectionRef: AngularFirestoreCollection<Todo>;
  todo$: Observable<Todo[]>;

我们映射 snapshotChanges 返回的 observable 以提取文档的 id 及其数据。

snapshotChanges 返回的操作属于 DocumentChangeAction 类型,并包含 类型payload。 类型是 addedmodifiedremoved 并且有效负载包含文档的 id、元数据和数据。


有了这个,一切都照旧,我们现在可以轻松地实现更新和删除 todo 文档,并将更改立即反映到我们的模板中:

app.component.ts(部分)

updateTodo(todo: Todo) {
  this.todoCollectionRef.doc(todo.id).update({ completed: !todo.completed });
}

deleteTodo(todo: Todo) {
  this.todoCollectionRef.doc(todo.id).delete();
}

了解更多