用小程序·雲開發打造功能全面的博客小程序丨實戰

用小程序·雲開發將博客小程序經常使用功能「一網打盡」javascript

本文介紹mini博客小程序的詳情頁的功能按鈕如何實現,具體包括評論、點贊、收藏和海報功能,這裏記錄下整個實現過程和實際編碼中的一些坑。css

評論、點贊、收藏功能

實現思路

實現文章的一些操做功能,最主要的仍是評論,這是做者和讀者之間溝通的橋樑,評論功能的衍生無非是細化做者和讀者之間的互動,或者增長文章的傳播,因此在動手開發時須要思考下你指望實現哪些功能,並對應功能進行細化。html

我通常的經驗是,先在腦子裏過一遍須要的功能和大體流程,而後在筆記稍微畫下「最最基礎的原型,至關於產品的角色」。java

而後就開始直接開始搭建頁面和簡單的交互「使用假數據,優先完成頁面」,在構造頁面的時候其實也可以補充最初想法上一些流程上的缺陷,這樣在設計後端和數據庫結構的時候能夠補上,總體下來也基本比較完善了。node

回頭看個人小程序的需求,首先確定是操做,在文章底部須要有個操做欄,用於發送點評和其餘一些操做,在參考了一些同類型的小程序以後,逐步實現本身的一套風格,樣式截圖以下:git

在有了功能以後,點評的數據須要有地方展現「一般是文章底部」,而後就有了文章底部的評論列表,樣式以下:github

既然有點贊收藏的功能按鈕,是否用戶須要看下我點贊和收藏的文章列表呢,因此在「個人」中就有相應的列表,樣式以下:數據庫

image

到這裏,最最基礎的功能基本差很少,接下來就要看後端是否能支持這些頁面了「主要就是數據的保存和展現了」npm

對於評論來講,確定須要一個集合用於保存用戶的評論,而對於用戶的喜歡和收藏也須要一個集合來進行保存。canvas

因此根據頁面咱們就能夠設計mini_commentsmini_posts_related兩個集合。前者用於保存評論數據,後者用戶保存用戶操做與文章之間的關聯。

剩下的工做就是變現了,無非就是頁面交互和數據的增刪改查了。

細節點解析

關於評論數量

目前在文章的集合中有個totalComments這個屬性,當這篇文章每新增一個評論時,須要加1。

最初在寫這個的時候,每次都是先查再更新,兩段式,原代碼以下:

let count=post.totalComments+1;

let result =await db.collection('mini_posts').doc(event.commentContent.postId).update({

​    data: {

​      totalComments: count

​    }

  });

複製代碼

後來看文檔發現,可使用db.command.inc這個指令,無需再查一遍,直接可對原字段加1,還能保證原子性。代碼以下:

const _ = db.command

let result = db.collection('mini_posts').doc(event.commentContent.postId).update({

​    data: {

​      totalComments: _.inc(1)

​    }

  });

複製代碼

關於新增子評論

須要實如今某個評論下進行回覆。

在交互上,點擊評論者的暱稱或頭像時,觸發相應的點擊事件,在事件中去記錄相應的評論ID及必要數據,同時去設置焦點到評論框內:

/**

  * 點擊評論內容回覆

  */

  focusComment: function (e) {

​    let that = this;

​    let name = e.currentTarget.dataset.name;

​    let commentId = e.currentTarget.dataset.id;

​    let openId = e.currentTarget.dataset.openid;



​    that.setData({

​      commentId: commentId,

​      placeholder: "回覆" + name + ":",

​      focus: true,

​      toName: name,

​      toOpenId: openId

​    });

  },

複製代碼

利用雲開發新增子評論時可使用db.command.push來進行操做「更新指令,對一個值爲數組的字段,往數組尾部添加一個或多個值」,往子評論集合中新增:

/**

 * 新增子評論

 * @param {} event 

 */

async function addPostChildComment(event) {



  let task = db.collection('mini_posts').doc(event.postId).update({

​    data: {

​      totalComments: _.inc(1)

​    }

  });

  await db.collection('mini_comments').doc(event.id).update({

​    data: {

​      childComment: _.push(event.comments)

​    }

  })

  await task;

}

複製代碼

關於判斷是否已收藏

在文章第一次加載時,咱們須要判斷下該用戶是否有對該文章有相關操做,若是有相應的收藏和點贊操做,在初始化時須要更新相應的功能圖標,核心代碼以下:

/**

   * 獲取收藏和喜歡的狀態

   */

  getPostRelated: async function (blogId) {

​    let where = {

​      postId: blogId,

​      openId: app.globalData.openid

​    }

​    let postRelated = await api.getPostRelated(where, 1);

​    let that = this;

​    for (var item of postRelated.data) {

​      if (config.postRelatedType.COLLECTION === item.type) {

​        that.setData({

​          collection: { status: true, text: "已收藏", icon: "favorfill" }

​        })

​        continue;

​      }

​      if (config.postRelatedType.ZAN === item.type) {

​        that.setData({

​          zan: { status: true, text: "已贊", icon: "appreciatefill" }

​        })

​        continue;

​      }

​    }

  },

複製代碼

至於其餘一些交互細節和代碼細節,能夠自行閱讀源碼去體會,若是有任何疑問或者有更好的實現方式,也能夠與我溝通。

海報功能

交代些背景

其實在最先以前的小程序中已經實現了一次,具體能夠參考利用雲開發優化博客小程序(三)——生成海報功能,主要仍是使用原生的cavans進行組裝,本來想代碼copy過來改改就好了,但總以爲原來的代碼寫的不是特別好。

因而想看看是否有現成的輪子能夠利用,果真發現了wxa-plugin-canvas這款組件,經過很是簡單的配置就能夠生成精美的海報。

小程序使用npm

在總結生成海報功能以前仍是有必要記錄下小程序npm的使用,避免一些沒必要要的坑。

考慮到小程序自己的大小限制,使用npm的方式是最佳的。

緣由是根據官方文檔介紹,小程序 npm 包裏只有構建文件生成目錄會被算入小程序包的佔用空間,上傳小程序代碼時也只會上傳該目錄的代碼。這樣大大減小了上傳的代碼體積。

下面簡單介紹下小程序端如何使用npm的「其實根據官方文檔按照步驟就能夠了」。

以我目前小程序的路徑爲例,在/miniprogram新增文件夾node_modules,在命令行指向到/miniprogram目錄下:

image

經過命令進行安裝:

npm install wxa-plugin-canvas --production  

複製代碼

安裝成功後,便可在小程序開發工具中進行構建,構建前須要勾選使用 npm 模塊

image

而後點擊開發者工具中的菜單欄:工具 --> 構建 npm便可:

image

構建完成後會生成miniprogram_npm目錄,到這裏,項目端基本就調通了。

wxa-plugin-canvas

在構建完以後,就能夠正常使用wxa-plugin-canvas這個自定義組件,使用方式仍是比較簡單的。

首先在你須要的頁面引入該組件:

{

  "usingComponents": {"poster": "wxa-plugin-canvas/poster"}

}

複製代碼

而後就能夠在wsml中使用了:

<poster id="poster" hide-loading="{{false}}" preload="{{false}}" config="{{posterConfig}}" bind:success="onPosterSuccess" bind:fail="onPosterFail"></poster>

複製代碼

因爲咱們在生成海報前,須要異步獲取一些用於海報的數據,因此咱們採用異步生成的海報方式。

須要引入該組件的poster/poster.js文件,而後在代碼中調用便可:

import Poster from '../../utils/poster';

Page({

​    /**

​     * 異步生成海報

​     */

​    onCreatePoster() {

​    	// setData配置數據

​    	this.setData({ posterConfig: {...} }, () => {

​        	Poster.create(); 

​    	});

​    }

})

複製代碼

核心代碼解析

海報須要的數據

先來看看分享海報的總體結構:

image

首先須要確認海報的構成須要哪些數據,在調用組件前先獲取好相應的數據。

在我設計的海報中主要包含三塊內容,用戶的信息(頭像和暱稱),文章信息(首圖,標題,簡介)和最重要的文章的小程序碼。

用戶信息和文章信息其實比較簡單,在小程序的詳情頁二者數據都有,但這裏有兩個問題點須要注意下。

第一個是域名問題,在畫布中使用到的圖片都須要配置域名,頭像的域名和公衆號文章首圖的域名

https://mmbiz.qpic.cn

https://wx.qlogo.cn

複製代碼

第二個是公衆號首圖的問題,公衆號素材列表返回的圖片url實際上是http的,但小程序規定綁定的域名必須是https的,當時比較無奈,後來嘗試改用https訪問首圖的url也能夠,不幸中的萬幸,因此在使用首圖地址時進行替換下:

imageUrl = imageUrl.replace('http://', 'https://')

複製代碼

最後就是文章的小程序碼了,須要利用小程序的getUnlimited的api,具體能夠參考官方文檔,目前已經提供了雲調用的方式「無需獲取access_token」,調用起來仍是比較簡單的。

本來打算在文章同步的時候「adminService」直接生成對應文章的小程序碼,代碼寫完後本地調試能夠,但上傳至雲端後測試發現一直報錯,逛了輪胎才知道原來不支持,同時觸發器也不支持雲調用,因此這個計劃泡湯了,我在代碼中打了TODO。

image

既然這樣,那就在生成海報的時候進行生成,同時生成後直接上傳至雲存儲,將對應的FileID保存至文章集合中,這樣只用生成一次就能夠一直使用了,具體代碼以下:

/**

 * 新增文章二維碼

 * @param {} event 

 */

async function addPostQrCode(event)

{

  let scene = 'timestamp=' + event.timestamp;

  let result = await cloud.openapi.wxacode.getUnlimited({

​    scene: scene,

​    page: 'pages/detail/detail'

  })



  if (result.errCode === 0) {

​    let upload = await cloud.uploadFile({

​      cloudPath: event.postId + '.png',

​      fileContent: result.buffer,

​    })



​    await db.collection("mini_posts").doc(event.postId).update({

​      data: {

​        qrCode: upload.fileID

​      }

​    });



​    let fileList = [upload.fileID]

​    let resultUrl = await cloud.getTempFileURL({

​      fileList,

​    })

​    return resultUrl.fileList

  }



  return []



}

複製代碼

但這裏有個尷尬的地方是,生成小程序碼的api中的scene參數最大長度是32,而文章id的長度已是32了,沒法根據文章id進行拼接跳轉頁面的路徑了,因此這裏暫時用了mini_posts集合中timestamp字段「理論上也是惟一的」。

因此在詳情頁中也須要兼容timestamp這個字段。

海報圖片展現

海報圖片展現就比較簡單了,使用個彈窗,將生成好的海報圖片進行展現便可:

/**

   * 生成海報成功-回調

   * @param {} e 

   */

  onPosterSuccess(e) {

​    const { detail } = e;

​    this.setData({

​      posterImageUrl: detail,

​      isShowPosterModal: true

​    })

​    console.info(detail)

  },

複製代碼

保存海報圖片

保存圖片使用wx.saveImageToPhotosAlbum調用用戶相冊,這裏主要須要兼容用戶拒絕相冊受權的一些列操做,具體代碼以下:

/**

  * 保存海報圖片

  */

  savePosterImage: function () {

​    let that = this

​    wx.saveImageToPhotosAlbum({

​      filePath: that.data.posterImageUrl,

​      success(result) {

​        console.log(result)

​        wx.showModal({

​          title: '提示',

​          content: '二維碼海報已存入手機相冊,趕快分享到朋友圈吧',

​          showCancel: false,

​          success: function (res) {

​            that.setData({

​              isShowPosterModal: false,

​              isShow: false

​            })

​          }

​        })

​      },

​      fail: function (err) {

​        console.log(err);

​        if (err.errMsg === "saveImageToPhotosAlbum:fail auth deny") {

​          console.log("再次發起受權");

​          wx.showModal({

​            title: '用戶未受權',

​            content: '如需保存海報圖片到相冊,需獲取受權.是否在受權管理中選中「保存到相冊」?',

​            showCancel: true,

​            success: function (res) {

​              if (res.confirm) {

​                console.log('用戶點擊肯定')

​                wx.openSetting({

​                  success: function success(res) {

​                    console.log('打開設置', res.authSetting);

​                    wx.openSetting({

​                      success(settingdata) {

​                        console.log(settingdata)

​                        if (settingdata.authSetting['scope.writePhotosAlbum']) {

​                          console.log('獲取保存到相冊權限成功');

​                        } else {

​                          console.log('獲取保存到相冊權限失敗');

​                        }

​                      }

​                    })



​                  }

​                });

​              }

​            }

​          })

​        }

​      }

​    });

  },

複製代碼

體驗總結

  • 有好的開源組件能夠充分利用,避免重複造輪子,有機會也能夠學習下別人的實現方式。

  • 多看看文檔,其實小程序的文檔真的挺詳細的。

  • 這裏主要想分享實現一個功能實現的過程,有想法的時候如何一步步去成功實現。

  • 小程序自己不難,相應的文檔也很詳細,可是組裝的過程和邏輯的實現須要自身去思考和體會。多看看文檔,其實小程序的文檔真的挺詳細的。

  • 若是你的想法和流程都很是清晰,但仍是沒辦法實現你的預期功能,那我建議你先放放,先把html,css,javascript熟悉下,再看幾遍小程序的文檔,也許你當時面臨的問題就再也不是問題了。

源碼連接

github.com/TencentClou…

相關文章
相關標籤/搜索