iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 15
2

在我們取得動態取得文章之前,先把我們的資料庫資料通通刪掉,等等才能確認我們的資料是否正確。

https://ithelp.ithome.com.tw/upload/images/20200923/20129819Cj9CpwEdf8.png

然後回到我們 Markdown 組件引用處 (ArticleEditor.vue),加上 onSave 事件 、以及 template 裡多加了一個 BootstrapVue 的 Modal 元件,他是會浮現在頁面上的另外一個懸浮視窗,可以用來確認 yes or no,這裡給他監聽一個 @ok 事件,用以上傳文章到資料庫:

ArticleEditor.vue 內...

<template>
  <b-container class="pageArticleEditor">
    <b-modal id="modal-1" title="是否新增文章" @ok="updateArticle">
      <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'
import { db } from '../Model/FirebaseModel.js'

export default {
  name: 'ArticleEditor',
  data () {
    return {
      title: '',
      articleData: {}
    }
  },
  components: {
    MarkdownPro
  },
  methods: {
    updateData (content) {
      this.articleData = content
      this.articleData.title = this.title

			// 文章上傳給他附帶一筆時間戳,這樣等等方便排序
      this.articleData.createdAt = new Date().getTime()
      // console.log(this.articleData)
			// 上次寫在首頁的 showUser 我把他寫成全域 mixin 的變數了
      this.articleData.articleInfo = this.showUser()

      // console.log(this.articleData)
    },

    updateArticle (data) {

      db.collection('posts').add(data).then(res => {
        console.log('新增文章成功')
      }).catch(res => {
        console.log('新增文章失敗')
      })

    }
  }
}
</script>

<style lang="scss" scope>
.pageArticleEditor {
  padding: 1rem;

  & > .row {
    & > div {
      margin: 1rem;;
    }
  }
}

.markdown-body {
  border: #aaa 2px solid;
  border-radius: 5px;
  height: 100%;
  padding: 1rem;
}
</style>

觸發懸浮 Modal 的上傳前置按鈕,注意 modal-1的部分是目標 Modal 的 id :

<b-button v-b-modal.modal-1 variant="primary">點擊新增文章</b-button>

我們在 updateData 方法內上傳十多添加了一筆純數字的時間標記,對時間物件不熟悉的話可以先去看看 MDN 的 Date 物件,this.articleData.createdAt = new Date().getTime() ,getTime() 會返回1970.01.01到目前為止經過的毫秒數,這樣的格式很方便,不僅方便可以排序,也能很輕易地轉換回幾年幾月幾日,我們先上傳文章。

第一篇寫好按下 Ctrl + s,先讓 updateData 方法把文章儲存好,再按 "點擊新增文章" 後會跳出懸浮 Modal,然後再 OK,F12 中應該可以看到文章上傳成功。

https://ithelp.ithome.com.tw/upload/images/20200923/20129819G0b3lvrzfv.png

https://ithelp.ithome.com.tw/upload/images/20200923/20129819trapdX1ohq.png

然後再隨便打個三篇,記得要按 Ctrl + s 儲存 ( 套件本身有自動儲存的屬性可用,不過我還沒開起 ),不然資料會是舊的。

ArticleEditor.vue 的內容沒問題也正確上傳後,這裡會發現我們的資料上傳後都不是按照順序,這裡就不貼圖,大家寫幾個資料進去看看就知道了。

有了資料,終於可以來處理我們那煩人的 posts id 重複問題了,回到 Articles.vue 組件,修改成下面:

<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.value }}</p>
      </div>
      <div class="goto">
        <p> >> 繼續閱讀</p>
      </div>
    </div>
  </div>
</template>

<script>
import { db } from '../Model/FirebaseModel.js'
export default {
  name: 'Article',
  props: {
    msg: String
  },
  created () {
    const self = this

    // 看我底下提供的排序連結,desc 是降序
    db.collection('posts').orderBy('createdAt', 'desc').get().then(function (querySnapshot) {
      querySnapshot.forEach(function (doc) {
        // doc.data() is never undefined for query doc snapshots
        // 自行觀察一下 doc.id 和 doc.data() 會是什麼。
        console.log(doc.id, ' => ', doc.data())
        const data = doc.data()

        // 新增id成員讓 v-for 去綁定每筆不同的 id 值,到這裡終於不會再有重複錯誤了
        data.id = doc.id
        self.posts.push(data)
      })
    })
  },
  data () {
    return {
      posts: [
      ]
    }
  }
}
</script>

程式中的排序方法在這,會把資料排序後再回傳 :

https://firebase.google.com/docs/firestore/query-data/order-limit-data?authuser=0

注意,這裡要改成 xxx.value,原本是 xxx.content,除非當初上傳文章那邊要把它的成員名稱換成 content。知道這點後,基本上就是前後端的 API 串接了,其實一點都不難。

https://ithelp.ithome.com.tw/upload/images/20200923/20129819Vq4WG4amhj.png

我們以時間為基準來排序,也就是當初我們上傳文章時都會附帶的一筆 createdAt 的時間戳記,如此一來,每次我們在讀入網頁時,就會以時間降序抓下我們的文章分才能正確接出資料。

https://ithelp.ithome.com.tw/upload/images/20200923/20129819xAWBm1ohPn.png

OK,今天就先到這邊,我們明天來處理寫文章時, <!— more —> 後面應該要隱藏起來,這是 hexo 框架或一些其他框架另外處理的功能,並不是 Markdown 的語法喔,有些使用 hexo 的朋友可能會誤會這點。

目前我們都是很陽春的功能,沒有做其他的例外處理,比如說登入失敗的提示訊息、文章上傳若內容為空等等其他細節部份等功能差不多了再一一的列清單出來處理哈哈,趕進度先阿 ~~


沒事也可以逛逛我們其他團隊成員的文章啦 ~~
eien_zheng: 前端小嘍嘍的Golang學習旅程_The journey of learning Golang 系列
PollyPO技術: 前端設計轉前端工程師-JS踩坑雜記 30 天 系列
阿電: 忍住不打牌位,只要30天VueJS帶你上A牌 系列
喬依司: 實作經典 JavaScript 30 系列


上一篇
Day 14: 借個別人的套件,給自己文章編輯 Markdown 一下
下一篇
Day 16: 模仿 hexo 實作 <!-- more --> 功能使文章斷開
系列文
Vue CLI + Firebase 雲端資料庫 30天打造簡易部落格及後臺管理30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言