昨天不僅完成了 Vuex Module Registration,
也完成了串接 Firebase 登入/登出/自動登入。
今天來建立部落格所有需要的資料庫結構,簡單分為兩個 vuex modules:
tags 這個 module 的內容只有一個 action,
就是 getAllTags
,直接來看程式碼:
import { db } from '@/services/fireinit'
import { uniq, flatten } from 'lodash'
export const actions = {
getAllTags () {
let postsCol = db.collection('posts').where('isShow', '==', true)
return postsCol.orderBy('postTime', 'desc').get()
.then(({ docs }) => {
let allTags = []
docs.forEach(doc => {
allTags.push(doc.data().tags)
})
allTags = uniq(flatten(allTags))
const promises = allTags.map(tag => {
return postsCol.where('tags', 'array-contains', tag).get()
.then(({ docs }) => {
return {
name: tag,
size: docs.length,
}
})
})
return Promise.all(promises)
})
}
}
import { db } from '@/services/fireinit'
fireinit 是前天寫好的套件,將 firestore export 為 db
,
這樣就可以透過 db
與 firestore 溝通(存、取、修改、刪除)。
import { uniq, flatten } from 'lodash'
從所有的文章中取出 tags, 並且透過 flatten 和 uniq 移除重複的部分。
post 有 7 個 actions:
部落格作者
使用者
由於這個 module 的程式碼較多,這邊就以 action 來分別介紹:
使用 db.collection('posts').add
新增文章,
成功回傳的 data 會自帶 data.id 作為辨別一篇文章的 postId。
而這個 action 會在元件 FormAddPost 被用到。
addPost ({}, payload) {
return db.collection('posts').add({ ...payload })
.then(data => ({ id: data.id, ...payload }))
}
修改一篇文章首先需要該篇文章的 postId,
這邊透過 set
並帶入參數 merge: true
自動合併。
而這個 action 會在元件 FormAddPost 被用到。
setPost ({}, payload) {
return db.collection('posts').doc(payload.postId).set({ ...payload.thePost }, { merge: true })
.then(() => ({ ...payload.thePost, id: payload.postId }))
}
列出所有文章,並用 orderBy('postTime', 'desc)
按照發布時間排序。
getPostsAdmin () {
return db.collection('posts').orderBy('postTime', 'desc').get()
.then(docs => {
const posts = []
docs.forEach(doc => {
posts.push({ ...doc.data(), id: doc.id })
})
return posts
})
}
列出第 payload.pageNum
頁,
且一頁最多 payload.perPage
筆文章,
且使用 where('isShow', '==', true)
只顯示使用者可以看到的文章。
async getPostsByPage ({}, payload) {
let postsCol = db.collection('posts').where('isShow', '==', true).orderBy('postTime', 'desc')
let docs = await postsCol.get()
.then(({ docs }) => docs)
let startAt = (payload.pageNum - 1) * payload.perPage
let page = docs[startAt] ? Number(payload.pageNum) : 1
let size = docs.length
let pageLength = Math.ceil(size / payload.perPage)
if (size === 0) return {
page: 1,
size: 1,
posts: []
}
let postTime = docs[startAt]
? docs[startAt].data().postTime
: docs[0].data().postTime
return await postsCol.startAt(postTime).limit(payload.perPage).get()
.then(({ docs }) => {
const posts = []
docs.forEach(doc => {
posts.push({ ...doc.data(), id: doc.id })
})
return {
page,
pageLength,
posts
}
})
}
透過 where('tags', 'array-contains', tagId)
來篩選出擁有該標籤的所有文章。
getPostsTag ({}, tagId) {
return db.collection('posts').where('isShow', '==', true).where('tags', 'array-contains', tagId).get()
.then(docs => {
const posts = []
docs.forEach(doc => {
posts.push({ ...doc.data(), id: doc.id })
})
return posts
})
}
根據 postId 取的該文章內容。
getPostByPostId ({}, postId) {
return db.collection('posts').doc(postId).get()
.then(doc => doc.data())
}
取得所有使用者可見的文章列表,並按照發布日期排序。
getPosts () {
return db.collection('posts').where('isShow', '==', true).orderBy('postTime', 'desc').get()
.then(({ docs }) => {
const posts = []
docs.forEach(doc => {
posts.push({ ...doc.data(), id: doc.id })
})
return posts
})
}
注意:記得要回 firebase 的 Database 建立索引如下圖:
明天開始利用這些開發好的 actions 切版,
今天就暫時無法 Demo 了。
指令:
git clone -b 023-module-tags-post --single-branch https://github.com/hunterliu1003/blog.git
cd blog
npm install