跳到主要内容
2024年开发商调查在这里,我们很想听听您的意见!
参加2024年开发商调查
667
0

自从firebase v9发布以来,客户端的包大小已经大大减小,现在只导入和绑定了使用的函数。

但这种模块化有其自身的权衡。如果代码很复杂并且使用了更多的firebase函数,那么代码就会变得混乱。为了解决这个问题,在typescript中创建了一个helper类,它是类型安全的,并提供了一种更干净、可读的使用firebase函数的方法。

对于本文,我们将只讨论firestore。

让我们首先导入将在这个自定义firestore类中使用的函数,并初始化firebase应用程序和firestore数据库。

从“firebase/app”导入{FirebaseApp,initializeApp}导入{文件参考,文档,获取文档,setDoc、,更新文档,删除文档,集合参考,收集,添加文档,获取文档,查询,查询文档快照,哪里,其中FilterOp,订单依据,按方向排序,限制,开始之后,从服务器获取计数,QueryFieldFilterConstraint,QueryOrderByConstraint,QueryLimitConstraint,查询限制约束,获取Firestore,Firestore、,}来自“firebase/firestore”let数据库:Firestorelet应用程序:FirebaseAppif(窗口类型!==“未定义”){app=初始化应用程序({/*您的配置*/})database=getFirestore(应用程序)}

以前的firestore实现主要由两部分组成(从高级角度来看)。它有集合,这些集合有文档。所以我们需要创建两个类,一个用于收藏另一个用于文件.

由于我们还需要类型安全,让我们从定义这些接口的外观开始

接口集合1{名称:字符串电子邮件:字符串//定义其他属性}接口集合2{消息:字符串时间戳:数字//定义其他属性}界面集合{集合1:集合1集合2:集合2}接口SubCollections{收集1:{subCollection1:{field:string}subCollection2:{field:string}}子集合1:{sub_c_1:{字段:字符串}}子集合2:{sub_c2:{字段:字符串}}}

既然已经定义了接口,那么可能会对为什么收藏&子集合接口就是这样创建的。这是为了在类型脚本中使用泛型,这些泛型在下面定义的类中用于类型安全。

N->名称,T->类型,S->子集合

类文档<N,T>{参考:文件参考构造函数(id:string){this.ref=doc(数据库,id)作为DocumentReference}//@ts-ignore公司集合<S扩展子集合[N]>的键(路径:S){//@ts-ignore公司return new Collection<S,SubCollections[N][S]>(`${this.ref.path}/${String(path)}`)}async get():承诺{const docSnapshot=等待getDoc(this.ref)if(docSnapshot.exists())返回docSnapshot.data()!引发新错误(“文档不存在”)}集合(数据:T){return setDoc(this.ref,data)}更新(数据:部分<T>){//@ts-ignore公司return updateDoc(this.ref,data)}删除(){返回deleteDoc(this.ref)}}类集合<N,T>{参考:集合参考private whereConstraint:QueryFieldFilterConstraint[]=[]private orderByConstraint:QueryOrderByConstraint[]=[]private limitConstraint:QueryLimitConstraint[]=[]private lastDoc:QueryDocumentSnapshot<T>|null=null构造函数(路径:字符串){this.ref=集合(数据库、路径)作为集合引用}文档(id:string){return新文档<N,T>(`${this.ref.path}/${id}`)}添加(数据:T){return addDoc(this.ref,数据)}getAll():承诺{return getDocs(this.ref).then((snapshot)=>snapshot.docs.map((doc)=>({…doc.data(),id:doc.id}作为T))}其中<K extends keyof T>(字段:K,运算符:WhereFilterOp,值:T[K]){//@ts-ignore公司this.whereConstraint.push(其中(字段、运算符、值))把这个还给我}orderBy(字段:T键,方向:OrderByDirection){//@ts-ignore公司this.orderByConstraint=[orderBy(字段,方向)]把这个还给我}限制(大小:数字){this.limitConstraint=[限制(大小)]把这个还给我}异步查询():承诺{const constraints=[…this.whereConstraint,…this.orderByConstraint…this.limitConstraint]if(this.lastDoc)constraints.push(startAfter(this.lastDoc)as any)const querySnapshot=查询(this.ref,…constraints)const快照=等待getDocs(querySnapshot)this.lastDoc=快照.docs[snapshot.docs.length-1]return snapshot.docs.map((doc)=>({…doc.data(),id:doc.id}作为T))}异步计数():承诺{const querySnapshot=查询(this.ref,…this.whereConstraint)const快照=等待getCountFromServer(querySnapshot)返回snapshot.data().count}}

现在收藏文件类已创建,我们可以创建自定义存储类

类存储{集合<N extends keyof Collections>(路径:N){return新集合<N,集合[N]>(路径)}}

示例用法

const存储=新存储()//将新文档添加到集合store.collection('collection1').add({name:'name',email:'email'})//使用自定义id创建新文档store.collection('collection1').doc('docId').set({name:'name',email:'email'})//访问子集合中的文档store.collection('collection1').doc('docId').collection(`subCollection1').doc('sub_docId').colection(` sub_c_1').get()