#ironman/2018/我或許沒那麼懂Web
本系列文前面介紹了 Vue.js 的資料繫結與渲染的原理,後面介紹了 Cloud Firestore 的使用概念,今天就來介紹如何整合兩個作為總結吧!
Firebase 官方有自己維護的 SDK,請參見:GitHub - firebase/firebase-js-sdk: Firebase Javascript SDK。而 Vue.js 官方也有針對整合 Firebase 出了一個 JS 套件,就叫做 Vuefire,可參見:vuefire/packages/vuefire at lerna · vuejs/vuefire · GitHub。
在進行下去以前,請先參照
Day 10: Cloud Firestore β: (2) 建立專案 & 文件
Day 20: Cloud Firestore β (12): 初始化
首先,我們先透過 Vue-CLI 建立一個 Vue 專案:
# 安裝 Vue CLI
npm install -g vue-cli
# 建立一個 Vue 專案
vue init webpack burning-ironman
cd burning-ironman
加入 Firebase JS SDK 和 VueFire 套件,並安裝所有相依套件。
yarn add firebase vuefire@next
yatn install
可能是因為 Cloud Firestore 還處於測試版中,vuefire 在支援 Cloud Firestore 的部分也處於 Alpha 的狀態,並透過 Lerna 進行套件管理,若是要安裝有支援的版本,我們就要使用其在 npm 上的 next 版本。
編輯 ./src/main.js
,引入相關套件並且加入資料庫初始化設定。
// src/main.js
import VueFire from 'vuefire'
import firebase from 'firebase/app'
import 'firebase/firestore'
Vue.use(VueFire)
firebase.initializeApp({
projectId: 'YOUR_PROJECT_ID',
databaseURL: 'YOUR_DB_URL'
})
export const db = firebase.firestore()
或者你也可以像我一樣將資料庫設定與 VueFire 分開:
// src/main.js
import VueFire from 'vuefire'
Vue.use(VueFire)
// src/db.js
import firebase from 'firebase/app'
import 'firebase/firestore'
// Initialize your firebase app
firebase.initializeApp({
projectId: 'YOUR_PROJECT_ID',
databaseURL: 'YOUR_DB_URL'
})
firebase.firestore().settings({ timestampsInSnapshots: true })
export const db = firebase.firestore()
我們以專案預設生成的 HelloWorld.vue
為例。首先我們要在 data()
回傳的資料物件中建立一個屬性用來存取資料, 並且給他初始值,避免在 Cloud Firestore 取得資料前就被用,引發 undefined
造成的程式出錯。然後再到 firestore()
回傳的資料物件中使用剛剛在 data()
建立的屬性鍵名去賦值。db
引入自我們剛剛建立的 db.js
所初始化的資料庫,用這個下查詢方法就可以了。
import { db } from '../db'
export default {
name: 'HelloWorld',
data () {
return {
districts: []
}
},
firestore () {
return {
districts: db.collection('districts').orderBy('name')
}
}
}
如此一來我們就可以在 Template 中使用:
<template>
<div>
<article v-for="(district, idx) in districts" :key="idx">
<h1>{{ district.name }}</h1>
<ul>
<li>City: {{ district.city }}</li>
<li>Population: {{ district.population }}</li>
</ul>
</article>
</div>
</template>
如果是要新增資料,則可以在 method()
返回的物件中建立對應方法,然後在裡面使用 db:
export default {
name: 'HelloWorld',
data () {
return {
districts: [],
formMessage: '',
formName: '',
formPopulation
}
},
firestore () {
return {
districts: db.collection('districts').orderBy('name')
}
},
methods: {
addDistrict () {
if (this.formName === '' || this.formPopulation === '') {
this.formMessage = '資料不完全!'
}
db.collection('districts')
.add({ this.formName, this.formPopulation })
.then(() => {
this.formName = ''
this.formPopulation = ''
this.formMessage = '已成功新增一個行政區!'
})
.catch(() => {
this.formMessage = '資料在送出時遇到問題!'
})
}
}
}
<template>
<form @submit="addDistrict()">
<p>{{formMessage}}</p>
<input v-model="formName" placeholder="District Name">
<input v-model="formPopulation" placeholder="District Population">
<button type="submit">Add District</button>
</form>
</template>
至於更新和刪除都是類似的方式,就不做示範了。
VueFire 取得資料的方式,一律都是使用 onSnapshot()
,所以當伺服器上的資料有變動時,也會即時更新網頁上的資訊,這部分就不需要另外再處理了。可以參見其原始碼:
data () {
return {
districts: []
}
},
firestore () {
return {
locations: db.collection('districts').orderBy('name')
}
}
上面那段code我會報錯,把 firestore 裡面 return 的 locations
改成 districts
就對囉!
感謝回報,的確是這樣。原因在於這段程式碼在 data() {} 中有宣告的索引是 districts
,不是 locations
。我已經修正了,再次感謝您。 = D