1. 程式人生 > >mpvue+小程式雲開發,純前端實現婚禮邀請函(相簿小程式)

mpvue+小程式雲開發,純前端實現婚禮邀請函(相簿小程式)

請勿使用本文章及原始碼作為商業用途!

前言

當初做這個小程式是為了婚禮前的需要,結婚之後,希望這個小程式能夠留存下來,特地花了一些空閒時間將小程式轉化成為“相簿類小程式”

體驗碼

準備工作

  1. mpvue框架 mpvue官方文件
  2. 小程式·雲開發 小程式·雲開發文件

注意:使用mpvue前,首先你得先熟悉vue框架的基本使用 

專案結構介紹

注意:接下來展示的程式碼,有幾個對比,分別是本人優化前和優化後的程式碼對比,感興趣的可以著重看一下優化後的成熟寫法。

  • common目錄: 放一些公共資源,如js,css,json
  • components目錄:元件相關的.vue檔案都放在這裡
  • pages目錄:所有頁面都放在這個目錄
  • utils目錄:使用mpvue時自動生成,可忽略
  • app.json檔案:
{
  "pages": [
    "pages/index/main",
    "pages/photo/main",
    "pages/map/main",
    "pages/greet/main",
    "pages/message/main"
  ],
  "window": {
    "backgroundTextStyle": "light",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "WeChat",
    "navigationBarTextStyle": "black"
  },
  "tabBar": {
    "color": "#ccc",
    "selectedColor": "#ff4c91",
    "borderStyle": "white",
    "backgroundColor": "#ffffff",
    "list": [
      {
          "pagePath": "pages/index/main",
          "iconPath": "static/images/1-1.png",
          "selectedIconPath": "static/images/1-2.png",
          "text": "邀請函"
      },
      {
          "pagePath": "pages/photo/main",
          "iconPath": "static/images/2-1.png",
          "selectedIconPath": "static/images/2-2.png",
          "text": "甜蜜相簿"
      },
      {
          "pagePath": "pages/map/main",
          "iconPath": "static/images/3-1.png",
          "selectedIconPath": "static/images/3-2.png",
          "text": "酒店導航"
      },
      {
          "pagePath": "pages/greet/main",
          "iconPath": "static/images/4-1.png",
          "selectedIconPath": "static/images/4-2.png",
          "text": "好友祝福"
      },
      {
          "pagePath": "pages/message/main",
          "iconPath": "static/images/5-1.png",
          "selectedIconPath": "static/images/5-2.png",
          "text": "留言評論"
      }
    ]
  },
  "requiredBackgroundModes": ["audio"]
}
  • App.vue檔案 (本人主要是為了增加專案更新後的提醒),所以在這個檔案加了些相關內容,內容如下:
<script>
export default {
  onLaunch () {
    // 檢測小程式是否有新版本更新
    if (wx.canIUse('getUpdateManager')) {
      const updateManager = wx.getUpdateManager()
      updateManager.onCheckForUpdate(function (res) {
        // 請求完新版本資訊的回撥
        if (res.hasUpdate) {
          updateManager.onUpdateReady(function () {
            wx.showModal({
              title: '更新提示',
              content: '新版本已經準備好,是否重啟應用?',
              success: function (res) {
                if (res.confirm) {
                  // 新的版本已經下載好,呼叫 applyUpdate 應用新版本並重啟
                  updateManager.applyUpdate()
                }
              }
            })
          })
          // 小程式有新版本,會主動觸發下載操作(無需開發者觸發)
          wx.getUpdateManager().onUpdateFailed(function () {
            // 當新版本下載失敗,會進行回撥
            wx.showModal({
              title: '提示',
              content: '檢查到有新版本,下載失敗,請檢查網路設定',
              showCancel: false
            })
          })
        }
      })
    } else { // 版本過低則無法使用該方法
      wx.showModal({
        title: '提示',
        confirmColor: '#5BB53C',
        content: '當前微信版本過低,無法使用該功能,請升級到最新微信版本後重試。'
      })
    }
  }
}
</script>

<style lang="stylus">
page
    height 100%
image
    display block
</style>
  • main.js檔案:
import Vue from 'vue'
import App from './App'

Vue.config.productionTip = false
App.mpType = 'app'

wx.cloud.init({
  env: '雲開發環境ID'
})

const app = new Vue(App)
app.$mount()
  • functions目錄:主要放一些雲函式,這裡不清楚雲函式的文章後面會提及
  • images目錄:主要放一些靜態資源圖片

頁面介紹

首頁——邀請函

首頁著重和大家講解下背景音樂的實現方法

const audioCtx = wx.createInnerAudioContext()

wx.createInnerAudioContext 介面獲取例項

接著,通過例項的相關方法來實現音樂的播放與暫停功能

關於小程式音訊相關文件

具體程式碼如下:

<script>
import IndexSwiper from 'components/indexSwiper'
import tools from 'common/js/h_tools'
const audioCtx = wx.createInnerAudioContext()
export default {
  name: 'Index',
  components: {
    IndexSwiper
  },
  data () {
    return {
      isPlay: true,
      list: []
    }
  },
  onShow () {
    const that = this
    that.isPlay = true
    that.getMusicUrl()
  },

  methods: {
    audioPlay () {
      const that = this
      if (that.isPlay) {
        audioCtx.pause()
        that.isPlay = false
        tools.showToast('您已暫停音樂播放~')
      } else {
        audioCtx.play()
        that.isPlay = true
        tools.showToast('背景音樂已開啟~')
      }
    },

    getList () {
      const that = this
      const db = wx.cloud.database()
      const banner = db.collection('banner')
      banner.get().then(res => {
        that.list = res.data[0].bannerList
      })
    },

    getMusicUrl () {
      const that = this
      const db = wx.cloud.database()
      const music = db.collection('music')
      music.get().then(res => {
        let musicUrl = res.data[0].musicUrl
        audioCtx.src = musicUrl
        audioCtx.loop = true
        audioCtx.play()
        that.getList()
      })
    }
  },

  onShareAppMessage: function (res) {
    return {
      path: '/pages/index/main'
    }
  }
}
</script>

以上程式碼中使用到了雲開發相關功能,文章後面會介紹,請大家稍安勿躁

相簿頁——就一個輪播圖,這裡就不過多介紹

地圖頁——這裡著重講一下地圖標籤map

map標籤 關於map元件的使用文件

這裡講一下標記點markers:

data () {
    return {
      // qqSdk: '',
      markers: [{
        iconPath: '../../static/images/nav.png',
        id: 0,
        latitude: 30.08059,
        longitude: 115.93027,
        width: 50,
        height: 50
      }]
    }
  }
<template>
    <div class="map">
        <image mode="aspectFit" class="head-img" src="../../static/images/t1.png"/>
        <map class="content" id="map" longitude="115.93027" latitude="30.08059" :markers="markers" scale="18" @tap="toNav">
        </map>
        <div class="call">
            <div class="left" @tap="linkHe">
                <image src="../../static/images/he.png"/>
                <span>呼叫新郎</span>
            </div>
            <div class="right" @tap="linkShe">
                <image src="../../static/images/she.png"/>
                <span>呼叫新娘</span>
            </div>
        </div>
        <image class="footer" src="../../static/images/grren-flower-line.png"/>
    </div>
</template>

祝福頁——也是雲開發相關內容,後面會介紹

留言頁——也是雲開發相關內容,後面會介紹

雲開發介紹

小程式雲開發文件

project.config.json檔案:

"cloudfunctionRoot": "static/functions/"

進行雲開發首先我們需要找到上面這個檔案,在上面這個json檔案中加上上面這行程式碼

cloudfunctionRoot 用於指定存放雲函式的目錄

app.json檔案:

"window": {
    "backgroundTextStyle": "light",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "WeChat",
    "navigationBarTextStyle": "black"
},
"cloud": true

增加欄位 "cloud": true實現雲開發能力的相容性

開通雲開發

在開發者工具工具欄左側,點選 “雲開發” 按鈕即可開通雲開發

雲開發控制檯

資料庫

 雲開發提供了一個 JSON 資料庫

 

儲存

 

雲開發提供了一塊儲存空間,提供了上傳檔案到雲端、帶許可權管理的雲端下載能力,開發者可以在小程式端和雲函式端通過 API 使用雲端儲存功能。

 

雲函式

 

雲函式是一段執行在雲端的程式碼,無需管理伺服器,在開發工具內編寫、一鍵上傳部署即可執行後端程式碼。

使用雲開發

雲能力初始化

在小程式端開始使用雲能力前,需先呼叫 wx.cloud.init 方法完成雲能力初始化

import Vue from 'vue'
import App from './App'

Vue.config.productionTip = false
App.mpType = 'app'

wx.cloud.init({
  env: '雲開發環境ID'
})

const app = new Vue(App)
app.$mount()

資料庫的使用

在開始使用資料庫 API 進行增刪改查操作之前,需要先獲取資料庫的引用。以下呼叫獲取預設環境的資料庫的引用:

const db = wx.cloud.database()

 要操作一個集合,需先獲取它的引用:

const todos = db.collection('todos')

操作資料庫的相關示例

例:首頁獲取背景音樂資源

getMusicUrl () {
      const that = this
      const db = wx.cloud.database()
      const music = db.collection('music')
      music.get().then(res => {
        let musicUrl = res.data[0].musicUrl
        audioCtx.src = musicUrl
        audioCtx.loop = true
        audioCtx.play()
        that.getList()
      })
}

 例:首頁獲取輪播圖陣列

getList () {
      const that = this
      const db = wx.cloud.database()
      const banner = db.collection('banner')
      banner.get().then(res => {
        that.list = res.data[0].bannerList
      })
}

例:祝福頁,使用者送上祝福儲存使用者

<script>
import tools from 'common/js/h_tools'
export default {
  name: 'Greet',
  data () {
    return {
      userList: [],
      openId: '',
      userInfo: ''
    }
  },
  onShow () {
    const that = this
    that.getUserList()
  },
  methods: {
    scroll (e) {
      console.log(e)
    },

    sendGreet (e) {
      const that = this
      if (e.target.errMsg === 'getUserInfo:ok') {
        wx.getUserInfo({
          success: function (res) {
            that.userInfo = res.userInfo
            that.getOpenId()
          }
        })
      }
    },

    addUser () {
      const that = this
      const db = wx.cloud.database()
      const user = db.collection('user')
      user.add({
        data: {
          user: that.userInfo
        }
      }).then(res => {
        that.getUserList()
      })
    },

    getOpenId () {
      const that = this
      wx.cloud.callFunction({
        name: 'user',
        data: {}
      }).then(res => {
        that.openId = res.result.openid
        that.getIsExist()
      })
    },

    getIsExist () {
      const that = this
      const db = wx.cloud.database()
      const user = db.collection('user')
      user.where({
        _openid: that.openId
      }).get().then(res => {
        if (res.data.length === 0) {
          that.addUser()
        } else {
          tools.showToast('您已經送過祝福了~')
        }
      })
    },

    getUserList () {
      const that = this
      wx.cloud.callFunction({
        name: 'userList',
        data: {}
      }).then(res => {
        that.userList = res.result.data.reverse()
      })
    }
  }
}
</script>

獲取送祝福的好友列表

getUserList () {
      const that = this
      wx.cloud.callFunction({
        name: 'userList',
        data: {}
      }).then(res => {
        that.userList = res.result.data.reverse()
      })
}

這裡用到了雲函式,之所以用雲函式是因為小程式端在獲取集合資料時伺服器一次預設並且最多返回 20 條記錄,雲函式端這個數字則是 100。

雲函式的使用方法

上面我們講過在project.config.json檔案中配置雲函式存放位置

下面是雲函式messageList的index.js檔案:

不成熟寫法:

const cloud = require('wx-server-sdk')
cloud.init()
const db = cloud.database()
const MAX_LIMIT = 100
exports.main = async (event, context) => {
  // 先取出集合記錄總數
  const countResult = await db.collection('message').count()
  const total = countResult.total
  // 計算需分幾次取
  const batchTimes = Math.ceil(total / 100)
  // 承載所有讀操作的 promise 的陣列
  const tasks = []
  for (let i = 0; i < batchTimes; i++) {
    const promise = db.collection('message').skip(i * MAX_LIMIT).limit(MAX_LIMIT).get()
    tasks.push(promise)
  }
  // 等待所有
  return (await Promise.all(tasks)).reduce((acc, cur) => ({
    data: acc.data.concat(cur.data),
    errMsg: acc.errMsg
  }))
}
成熟寫法(分頁查詢):
const cloud = require('wx-server-sdk')
cloud.init()
const db = cloud.database()
exports.main = async (event, context) => {
  const wxContext = cloud.getWXContext()
  const dbName = 'message'
  const filter = event.filter ? event.filter : null
  const pageNum = event.pageNum ? event.pageNum : 1
  const pageSize = event.pageSize ? event.pageSize : 10
  const countResult = await db.collection(dbName).where(filter).count()
  const total = countResult.total
  const totalPage = Math.ceil(total / pageSize)
  let hasMore
  if (pageNum >= totalPage) {
    hasMore = false
  } else {
    hasMore = true
  }
  return db.collection(dbName).orderBy('time', 'desc').where(filter).skip((pageNum - 1) * pageSize).limit(pageSize).get().then(res => {
    res.hasMore = hasMore
    res.total = total
    res.openId = wxContext.OPENID
    return res
  })
}

使用雲函式前,在開發者工具上,找到messageList目錄,右鍵如圖:

 點選上傳並部署:雲端安裝依賴(不上傳node_modules)

得到如圖的提示:

 安裝完點選完成就能使用當前雲函數了,使用方法即:

getUserList () {
      const that = this
      wx.cloud.callFunction({
        name: 'userList',
        data: {}
      }).then(res => {
        that.userList = res.result.data.reverse()
      })
}

陣列之所以要倒序是因為希望新祝福的的使用者在最前面顯示 

使用者送上祝福的時候儲存使用者

這裡我們用到了雲函式獲取使用者資訊,

當小程式端呼叫雲函式時,雲函式的傳入引數中會被注入小程式端使用者的 openid,開發者無需校驗 openid 的正確性,因為微信已經完成了這部分鑑權,開發者可以直接使用該 openid

不成熟寫法:

下面是雲函式user的index.js檔案:

// 雲函式入口檔案
const cloud = require('wx-server-sdk')

cloud.init()

// 雲函式入口函式
exports.main = async (event, context) => {
  const wxContext = cloud.getWXContext()

  return {
    event,
    openid: wxContext.OPENID,
    appid: wxContext.APPID,
    unionid: wxContext.UNIONID
  }
}

主要是為了獲取當前操作使用者的openid,獲取當前使用者的openid方法:

getOpenId () {
      const that = this
      wx.cloud.callFunction({
        name: 'user',
        data: {}
      }).then(res => {
        that.openId = res.result.openid
        that.getIsExist()
      })
}

接著判斷當前使用者是否已經存在於資料庫中,即getIsExist()方法:

getIsExist () {
      const that = this
      const db = wx.cloud.database()
      const user = db.collection('user')
      user.where({
        _openid: that.openId
      }).get().then(res => {
        if (res.data.length === 0) {
          that.addUser()
        } else {
          tools.showToast('您已經送過祝福了~')
        }
      })
}

如果得到的陣列長度為零則新增改使用者到資料庫,否則則提醒當前使用者已經送過祝福

接下來介紹儲存使用者資訊的方法,即addUser():

addUser () {
      const that = this
      const db = wx.cloud.database()
      const user = db.collection('user')
      user.add({
        data: {
          user: that.userInfo
        }
      }).then(res => {
        that.getUserList()
      })
}

存入到資料庫的資訊是這樣的:

成熟寫法(使用雲函式一次搞定):

// 雲函式入口檔案
const cloud = require('wx-server-sdk')
cloud.init()
const db = cloud.database()
exports.main = async (event, context) => {
  const wxContext = cloud.getWXContext()
  const dbName = 'user'
  const filter = {
    _openid: wxContext.OPENID
  }
  const countResult = await db.collection(dbName).where(filter).count()
  const total = countResult.total
  if (total) {
    return {
      has: true
    }
  } else {
    return db.collection(dbName).add({
      data: {
        user: event.user,
        _openid: wxContext.OPENID,
        time: db.serverDate()
      }
    })
  }
}
toMessage (e) {
      const that = this
      if (e.target.errMsg === 'getUserInfo:ok') {
        wx.getUserInfo({
          success: function (res) {
            that.userInfo = res.userInfo
            wx.navigateTo({
              url: `/pages/writeMessage/main?avatar=${that.userInfo.avatarUrl}&name=${that.userInfo.nickName}`
            })
            that.addUser(that.userInfo)
          }
        })
      }
    },
    addUser (obj) {
      wx.cloud.callFunction({
        name: 'addUser',
        data: {
          user: obj
        }
      })
    }

總結 

大概的功能就是這麼多,希望可以幫助到大家,覺得寫得不錯的記得給作者點個贊,你們的支援是我不斷更新的最大動力!

原始碼地址

小程式原始碼在此​

後續優化

  • 留言稽核
  • 一些動畫效果
  • 分頁處理
  • 雲函式優化
  • 回到頂部

最後

希望對那些有想法又不會後臺開發的朋友一些啟示作用,祝你早日做出只屬於你自己的個人小