昨天稍微看了一下自己的文章進度,發現有個東西漏掉,DAY 18 的內容提到 FirebaseModel.vue ,F_ 開頭的方法,這是另外做來 Mixin 的模組檔,如果只看昨天的程式碼是不行的,非常抱歉請先在這章我們整理一隻 FirebaseModel.vue 出來,跟FirebaseModel.js 放在一起就可以了。
以下是目前 FirebaseModel.vue 的內容,已經先封裝到一個地步了,後續可能還會隨著專案進行有很多更動,這就是沒有好好規劃就開始挑戰30天的下場...。
其中有些程式碼目前還沒用到,後續章節慢慢帶入。
<template>
<span>
</span>
</template>
<script>
import { firebase, db } from './FirebaseModel.js'
export default {
methods: {
// 用來檢查目前登入者
// 這邊算是用用看 async 看之後使用程式碼上會不會比較好讀。
async F_showUser (e, msg) {
console.log('觸發了F_showUser')
var user = firebase.auth().currentUser
// var name, email, photoUrl, uid, emailVerified
console.log('F_showUser: ', user)
if (user != null) return user
else return null
},
// 登入方法
F_signIn (account, password) {
console.log('觸發了F_signIn')
firebase.auth().signInWithEmailAndPassword(account, password).then(() => {
console.log('登入成功')
this.F_showUser().then(user => {
this.$router.push(`/backend/${user.uid}`)
})
}).catch(function (error) {
// Handle Errors here.
var errorCode = error.code
var errorMessage = error.message
console.error(errorCode, errorMessage)
})
},
// 註冊方法
F_signUp (user) {
firebase.auth().createUserWithEmailAndPassword(user.account, user.password).then(() => {
this.F_setManagerData(user)
this.$router.push('/backend')
}).catch(function (error) {
// Handle Errors here.
var errorCode = error.code
var errorMessage = error.message
console.error(errorCode, errorMessage)
})
},
// 登出方法
F_signOut () {
console.log('觸發了F_signOut')
firebase.auth().signOut().then(function () {
// Sign-out successful.
console.log('登出成功')
})
},
// 新增文章方法 (原本是F_updateArticle,避免和更新文章名稱衝突)
F_addArticle (data) {
console.log('觸發了F_updateArticle')
db.collection('posts').add(data).then(res => {
console.log('新增文章成功')
}).catch(res => {
console.log('新增文章失敗')
})
},
F_updateArticle (data) {
// 方法待新增,編輯文章用
},
// 監看者方法
F_stateWatcher () {
console.log('監看者觸發')
firebase.auth().onAuthStateChanged(function (user) {
if (user) {
// User is signed in.
// var email = user.email
// var emailVerified = user.emailVerified
// var photoURL = user.photoURL
// var isAnonymous = user.isAnonymous
// var uid = user.uid
// var providerData = user.providerData
console.log('現在使用者: ', user)
} else {
console.log('logout')
//
}
})
},
// 確認已登入直接進後端
F_checkLogin () {
console.log('觸發了F_checkLogin')
this.F_showUser().then(res => {
console.log(res)
if (res === null) this.$router.push('login')
else this.$router.push(`backend/${id}`)
})
},
// 抓該容器下所有文件
F_getCollectionDocs (collection, orderBy) {
const docs = []
return db.collection(collection).orderBy(orderBy.where, orderBy.order).get().then(function (querySnapshot) {
querySnapshot.forEach(function (doc) {
const data = doc.data()
data.id = doc.id
docs.push(data)
})
return docs
})
},
// 註冊管理者
F_setManagerData (user) {
db.collection('manager').doc(user.name).set({
account: user.account,
password: user.password,
displayName: user.displayName,
name: user.name,
email: user.email,
phoneNumber: user.phoneNumber,
address: user.address
}).catch(function (error) {
console.error('Error writing document: ', error)
})
},
// 更新個人資料 ( 非完整 )
F_updateProfile (userInfo) {
console.log('觸發了F_updateProfile')
var user = firebase.auth().currentUser
return user.updateProfile({
displayName: userInfo.displayName
// photoURL: photoURL
})
},
F_getUserInfo () {
// 待新增,註冊完進入個人編輯頁用
},
// 更新個人資料 ( 完整 )
F_updateManagerInfo () {
// 待新增,個人編輯頁更新資料用
}
}
}
</script>
main.js 要去混入我們的 firebase 模組
import firebase from './Model/FirebaseModel.vue'
Vue.mixin(firebase)
其中更新個人資料 ( 非完整 ) 的方法特別注意一下,updateProfile 只能提供兩個選項,一個是 displayName,一個是 photoURL,文件在這:
https://firebase.google.com/docs/reference/js/firebase.User#updateprofile
然後我們的 ArticleEditor.vue 有作些更動,注意 @ok 部分直接使用了上面 mixin 的方法。
<template>
<b-container class="pageArticleEditor">
<b-modal id="modal-1" title="是否新增文章" @ok="F_addArticle(articleData)">
<p class="my-4">如要新增請按確認</p>
</b-modal>
<b-row>
<b-col cols="12">
<label for="input-large">文章標題:</label>
<b-form-input id="input-large" size="lg" placeholder="請輸入文章標題" v-model="title"></b-form-input>
</b-col>
<b-col cols="12">
<MarkdownPro
@on-save="updateData"
></MarkdownPro>
</b-col>
<b-col class="mt-2"><b-button v-b-modal.modal-1 variant="primary">點擊新增文章</b-button></b-col>
</b-row>
</b-container>
</template>
<script>
import { MarkdownPro } from 'vue-meditor'
export default {
name: 'ArticleEditor',
data () {
return {
title: '',
articleData: {}
}
},
components: {
MarkdownPro
},
methods: {
updateData (saveEventInfo) {
const splitter = '<!-- more -->'
if (saveEventInfo.value.indexOf(splitter) === -1) {
saveEventInfo.value = saveEventInfo.value.slice(0, 20) + splitter + saveEventInfo.value.slice(20)
}
saveEventInfo.stopOnMore = saveEventInfo.value.split(splitter)
saveEventInfo.stopOnMore = saveEventInfo.stopOnMore[0] + '...'
this.articleData = saveEventInfo
this.articleData.title = this.title
this.articleData.createdAt = new Date().getTime()
// 這邊算是用用看 async => .then 看會不會比較好讀。
this.F_showUser().then(res => {
const buffer = {
displayName: res.displayName,
email: res.email,
uid: res.uid,
photoURL: res.photoURL
}
this.articleData.authorInfo = buffer
})
}
}
}
</script>
articlePage.vue 也重整一下資料結構
<template>
<b-container fluid>
<b-row>
<b-col cols="8" offset="2">
<div class="article">
<div class="content__header">
<h3>{{ articleInfo.title }}</h3>
<p>文章作者: {{ articleInfo.authorInfo.email }}</p>
<p>上傳時間: {{ articleInfo.createdAt }}</p>
</div>
<div class="article__content" v-html="articleInfo.html"></div>
</div>
</b-col>
</b-row>
</b-container>
</template>
<script>
import { db } from '../Model/FirebaseModel.js'
export default {
name: 'ArticlePage',
data () {
return {
articleId: this.$route.params.articleId,
articleInfo: {
title: '',
createdAt: '',
authorInfo: {
displayName: '',
email: '',
uid: '',
photoURL: ''
}
}
}
},
created () {
const articleRef = db.collection('posts').doc(this.articleId)
articleRef.get().then((doc) => {
if (doc.exists) {
this.articleInfo = doc.data()
} else {
// doc.data() will be undefined in this case
console.log('No such document!')
}
}).catch(function (error) {
console.log('Error getting document:', error)
})
}
}
</script>
ArticleList.vue 也來優化一下,不要用 {target} 接出來,太難看了,讓他每次傳該迴圈的 id 值進去 click。
<template>
<div class="article__blocks">
<div class="article__blocks__block" v-for="article in posts" :key="article.id">
<div class="article__blocks__block_title">
<h3>{{ article.title }}</h3>
</div>
<div class="article__blocks__block_content">
<p>{{ article.stopOnMore }}</p>
</div>
<div class="goto" @click="gotoArticle(article.id)" :data-articleId="article.id">
<p> >> 繼續閱讀</p>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'ArticleList',
props: {
msg: String
},
created () {
this.F_getCollectionDocs('posts', { where: 'createdAt', order: 'desc' }).then(docs => {
this.posts = docs
})
},
data () {
return {
posts: [
]
}
},
methods: {
gotoArticle (articleID) {
const targetArticle = this.posts.find(ele => {
return articleID === ele.id
})
this.$router.push(`/article/${targetArticle.id}`)
}
}
}
</script>
今天算中場休息,複製程式碼 Mixin 一下,明天我們要來完善我們的註冊流程。
沒事也可以逛逛我們其他團隊成員的文章啦 ~~
eien_zheng: 前端小嘍嘍的Golang學習旅程_The journey of learning Golang 系列
PollyPO技術: 前端設計轉前端工程師-JS踩坑雜記 30 天 系列
阿電: 忍住不打牌位,只要30天VueJS帶你上A牌 系列
喬依司: 實作經典 JavaScript 30 系列