請勿使用本文章及源碼作為商業用途!
前言
當初做這個小程式是為了婚禮前的需要,結婚之後,希望這個小程式能夠留存下來,特地花了一些空閑時間将小程式轉化成為“相冊類小程式”
體驗碼
準備工作
注意:使用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檔案 (本人主要是為了增加項目更新後的提醒),是以在這個檔案加了些相關内容,内容如下:
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: '目前微信版本過低,無法使用該功能,請更新到最新微信版本後重試。'
})
}
}
}
page
height 100%
image
display block
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()
接着,通過執行個體的相關方法來實作音樂的播放與暫停功能
具體代碼如下:
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'
}
}
}
以上代碼中使用到了雲開發相關功能,文章後面會介紹,請大家稍安勿躁
相冊頁——就一個輪播圖,這裡就不過多介紹
地圖頁——這裡着重講一下地圖示簽map
這裡講一下标記點markers:
data () {
return {
// qqSdk: '',
markers: [{
iconPath: '../../static/images/nav.png',
id: 0,
latitude: 30.08059,
longitude: 115.93027,
width: 50,
height: 50
}]
}
}
呼叫新郎
呼叫新娘
祝福頁——也是雲開發相關内容,後面會介紹
留言頁——也是雲開發相關内容,後面會介紹
雲開發介紹
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
})
}
例:祝福頁,使用者送上祝福存儲使用者
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()
})
}
}
}
擷取送祝福的好友清單
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
}
})
}
總結
大概的功能就是這麼多,希望可以幫助到大家,覺得寫得不錯的記得給作者點個贊,你們的支援是我不斷更新的最大動力!
源碼位址
後續優化
留言稽核
一些動畫效果
分頁處理
雲函數優化
回到頂部
最後
一開始不清楚随筆和文章的差別,還是希望這篇随筆能展示在部落格園首頁(是以改成随筆),讓更多的朋友看到
希望對那些有想法又不會背景開發的朋友一些啟示作用,祝你早日做出隻屬于自己的小程式。