本文目錄:
- 1.冷啟動(dòng)與熱啟動(dòng)
- 2.小程序里不要頻繁的進(jìn)行setData
- 3.小程序的更新機(jī)制
- 4.小程序性能與體驗(yàn)優(yōu)化
- 5.場(chǎng)景值scene的作用與應(yīng)用場(chǎng)景
- 6.頁面收錄sitemap.json的作用與使用方法
- 7.云開發(fā)小程序上限審核流程
- 8.輪播圖圖片
- 9.歌單信息管理
- 10.發(fā)現(xiàn)信息管理
在不同的運(yùn)行環(huán)境下蛤签,邏輯層和渲染層的運(yùn)行位置都不同对碌,所以在小程序開發(fā)中,要多用真機(jī)去進(jìn)行調(diào)試先誉。
小程序的開發(fā)其實(shí)就是典型的客戶端原生與web技術(shù)結(jié)合的混合技術(shù)(Hybrid)
1.冷啟動(dòng)與熱啟動(dòng)
第一次打開小程序,雖然以前打開過聋溜,但是數(shù)據(jù)被小程序主動(dòng)銷毀了谆膳,再次啟動(dòng)也算是冷啟動(dòng),熱啟動(dòng):已經(jīng)打開了撮躁,在一定時(shí)間內(nèi)再次打開(大約5分鐘)漱病,這時(shí)候的打開只是從后臺(tái)切換到前臺(tái)把曼。
2.小程序里不要頻繁的進(jìn)行setData
不表現(xiàn)在頁面上的數(shù)據(jù),不需要定義在data中嗤军。直接定義全局變量就行了。因?yàn)槊看蝧etData都會(huì)觸發(fā)渲染層和系統(tǒng)層叙赚、邏輯層的通信老客。
3.小程序的更新機(jī)制
我們可以在app.js的onLaunch生命周期中震叮,添加代碼,進(jìn)行版本的檢查和更新苇瓣,把下面這個(gè)函數(shù)放在onLaunch()里面尉间,讓小程序啟動(dòng)的時(shí)候就檢查更新击罪。
checkUpdate() {
const updateManager = wx.getUpdateManager()
// 檢測(cè)版本更新
updateManager.onCheckForUpdate((res) => {
// 如果有版本更新的話
if (res.hasUpdate) {
updateManager.onUpdateReady(() => {
wx.showModal({
title: '更新提示',
content: '新版本已經(jīng)準(zhǔn)備好,是否重啟應(yīng)用',
// 如果用戶選擇的是確定
success(res) {
updateManager.applyUpdate()
}
})
})
}
})
}
4.小程序性能與體驗(yàn)優(yōu)化
- 合理設(shè)置可點(diǎn)擊元素的響應(yīng)區(qū)域大小
- 避免渲染頁面耗時(shí)過長(zhǎng)
- 避免執(zhí)行腳本時(shí)間過長(zhǎng)
- 對(duì)網(wǎng)絡(luò)請(qǐng)求做必要的緩存以避免多余的請(qǐng)求
- 不要引入未被使用的wxss樣式
- 所有資源請(qǐng)求建議使HTTPS眠副,更加安全
- 不要使用廢棄接口
- 避免過大的WXML節(jié)點(diǎn)數(shù)目
- 一個(gè)頁面少于1000個(gè)WXML節(jié)點(diǎn)
- 節(jié)點(diǎn)數(shù)深度少于30層
- 子節(jié)點(diǎn)數(shù)量不大于60個(gè)
- 避免將不可能被訪問到的頁面打包在小程序包里
- 及時(shí)回收定時(shí)器(小程序中的定時(shí)器都是全局的竣稽,不會(huì)隨便頁面切換而消失)
- 避免使用:active偽類來實(shí)現(xiàn)點(diǎn)擊態(tài)(使用navigator組件)
- 滾動(dòng)區(qū)域可開啟慣性滾動(dòng)以增強(qiáng)體驗(yàn)
IOS上:-webkit-overflow-scrolling:touch
- 避免出現(xiàn)任何的Javascript異常
- 所有請(qǐng)求的耗時(shí)不應(yīng)該太久,請(qǐng)求最好都要加上showloading,不要讓頁面處于假死狀態(tài)
- 避免短時(shí)間內(nèi)發(fā)起太多的圖片請(qǐng)求
- 避免短時(shí)間內(nèi)發(fā)起太多請(qǐng)求
setData的優(yōu)化
- 避免setData的數(shù)據(jù)過大(小程序的限制是每次1M以內(nèi))
- 避免setData的調(diào)用過于頻繁
- 避免將未綁定到WXML的變量傳入setData
setData是一個(gè)異步操作拧烦,this.data是同步操作钝计,setData的回調(diào)是所有同步任務(wù)完成后才去執(zhí)行齐佳,但是this.data的值我們可以直接拿到進(jìn)行使用
案例1:下面代碼的執(zhí)行順序是什么债沮?
test的初始值是0
console.log('test開始:'+this.test)
this.setData({
test:1
},()=>{
console.log('回調(diào)執(zhí)行')
})
console.log('test設(shè)置后:’+this.test)
for (let i =0;i<10000;i++){
for(let j=0;j<10000;j++){}
}
console.log('長(zhǎng)耗時(shí):'+this.test)
//test開始:0
//test設(shè)置后:1
//test長(zhǎng)耗時(shí):1
//回調(diào)執(zhí)行
案例2:setData改變對(duì)象的屬性值
testObj的默認(rèn)屬性為name:zhangsan,age:27
changeAge(){
this.setData({
testObj:{
age:28
}
})
}
如果直接像上面這樣設(shè)置的話疫衩,age屬性值確實(shí)是變了,但是name屬性就消失了童芹,正確的做法應(yīng)該是
changeAge(){
this.setData({
['testObj.age']:{
age:28
}
})
}
setData改變的值可以不事先在data中進(jìn)行定義鲤拿,但是建議所有需要setData并且在頁面上顯示的值都在data中進(jìn)行定義近顷。
小程序開發(fā)的性能檢查:測(cè)試器中有個(gè)界面是Audits,我們開始檢查后將頁面的所有功能都手動(dòng)操作一遍窒升,然后點(diǎn)擊Stop就會(huì)出現(xiàn)響應(yīng)的評(píng)分异剥,A是最好的
5.場(chǎng)景值scene的作用與應(yīng)用場(chǎng)景
有幾十種途徑可以進(jìn)行到小程序,每個(gè)途徑對(duì)應(yīng)著一個(gè)ID值冤寿,如掃描二維碼對(duì)應(yīng)的是1011督怜,長(zhǎng)按圖片識(shí)別二維碼對(duì)應(yīng)的1012
我們可以通過對(duì)應(yīng)的代碼設(shè)置,來實(shí)現(xiàn)根據(jù)不同的入口場(chǎng)景号杠,來實(shí)現(xiàn)頁面的分流,同時(shí)也可以很方便的進(jìn)行后期的數(shù)據(jù)統(tǒng)計(jì)屉凯。
在app.js中對(duì)應(yīng)的生命周期onShow()中添加代碼(onShow監(jiān)聽小程序的啟動(dòng)和切前臺(tái))
開發(fā)者工具的導(dǎo)航欄有個(gè)功能鍵“切后臺(tái)”眼溶,點(diǎn)擊后可以模擬小程序切入后臺(tái),然后可以選擇不同的場(chǎng)景來進(jìn)行小程序
onShow(options){
}
onLauch:監(jiān)聽小程序的初始化
onShow:監(jiān)聽小程序的啟動(dòng)和切換前臺(tái)
這兩個(gè)的options的結(jié)構(gòu)是一樣的灌旧,里面都有scene字段
options可以打印出來scene值,根據(jù)這個(gè)值的不同我們可以進(jìn)行不同的設(shè)置描融,同時(shí)onLaunch生命周期中有可以進(jìn)行打印衡蚂,有幾個(gè)特定的場(chǎng)景代表著來源是外部的應(yīng)用(其他小程序或者公眾號(hào)),如果是的話让歼,options的referrerInfo字段會(huì)出現(xiàn)appid值丽啡,對(duì)我們也很有用补箍。
6.頁面收錄sitemap.json的作用與使用方法
在sitemap沒出現(xiàn)之前,小程序的搜索只能通過分類的名稱坑雅,sitemap讓小程序的搜索也可以根據(jù)頁面內(nèi)容實(shí)現(xiàn)裹粤。(本質(zhì)就是小程序的搜索功能優(yōu)化)
小程序的官網(wǎng)設(shè)置頁面,有一個(gè)頁面收錄功能開關(guān)按鈕拇泣,默認(rèn)是開啟的
項(xiàng)目文件里默認(rèn)創(chuàng)建有sitemap.json矮锈,我們可以里面添加和改變配置苞笨,在page里面配置頁面,*代表所有頁面瀑凝。頁面參數(shù)params以及匹配規(guī)則matching都是可以自由配置的粤咪。
"action":"allow"http://允許被索引
"action":"disallow"http://不允許被索引
7.云開發(fā)小程序上限審核流程
微信公眾平臺(tái)=》版本管理
首先需要把項(xiàng)目提交成”體驗(yàn)版”,項(xiàng)目預(yù)覽只有項(xiàng)目成員才可以掃描二維碼進(jìn)行預(yù)覽藏杖,小程序成為“體驗(yàn)版”
微信開發(fā)者工具右上角有個(gè)按鈕”上傳”脉顿,上傳之后就生成了體驗(yàn)版,微信公眾平臺(tái)的版本管理中就有了對(duì)應(yīng)的“開發(fā)版本”来吩。
GitHub上搜索vue-element-admin弟疆,star最多的那個(gè)盗冷,我們選擇使用基礎(chǔ)模板vue-admin-template
克隆項(xiàng)目
git clone https://github.com/PanJiaChen/vue-admin-template.git
進(jìn)入項(xiàng)目目錄
cd vue-admin-template
安裝依賴
npm install
建議不要直接使用 cnpm 安裝以來,會(huì)有各種詭異的 bug柑司」埃可以通過如下操作解決 npm 下載速度慢的問題
npm install --registry=https://registry.npm.taobao.org
啟動(dòng)服務(wù)
npm run dev
問題:下載了之后npm run dev報(bào)錯(cuò)故爵,去掉vue.config.js中的open:true之后可以直接啟動(dòng),但是登陸報(bào)405錯(cuò)誤劲室。
后端框架我們選用koa
1.建立空文件夾
2.npm init -y
3.npm install koa
4.新建app.js作為入口文件
在nodejs中出現(xiàn)最多的就是異步操作
實(shí)現(xiàn)hello world
const Koa = require('koa')
const app = new Koa()
app.use(async (ctx)=>{
ctx.body = 'hello world'
})
app.listen(3000)
選用request來實(shí)現(xiàn)后端的發(fā)送請(qǐng)求
npm install request
npm install request-promise
獲取access_token的請(qǐng)求接口
GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
我們把請(qǐng)求獲得token的代碼封裝在utils文件夾中的getAccessToken.js文件中
const rp = require('request-promise')
const APPID = 'xxxx'
const APPSECRET = 'xxx'
const URL = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${APPID}&secret=${APPSECRET}`
const updateAccessToken = async () => {
const resStr = await rp(URL)
const res = JSON.parse(resStr)
console.log(res)
}
updateAccessToken()
這時(shí)候通過運(yùn)行g(shù)etAccessToken.js文件我們可以在控制臺(tái)上看到痹籍,我們已經(jīng)獲取到了token晦鞋,并且有效時(shí)間為7200s悠垛,我們選擇把獲取到的token,通過node寫入到j(luò)son文件中去斤讥。
寫入信息,需要引入fs和path兩個(gè)核心模塊派草,并且封裝一個(gè)可以讀取token的方法铛楣。同時(shí)讀取代碼的時(shí)候如果文件不存在,會(huì)報(bào)錯(cuò)鉴竭,我們需要進(jìn)行一個(gè)異常的捕獲岸浑。完整代碼如下
const rp = require('request-promise')
const APPID = 'xxx'
const APPSECRET = 'xxx'
const URL = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${APPID}&secret=${APPSECRET}`
// 引入兩個(gè)核心文件矢洲,一個(gè)用來讀取文件,一個(gè)用來獲得文件的絕對(duì)路徑
const fs = require('fs')
const path = require('path')
// 定義我們要寫入數(shù)據(jù)的文件路徑
const fileName = path.resolve(__dirname, './access_token.json')
const updateAccessToken = async () => {
const resStr = await rp(URL)
const res = JSON.parse(resStr)
console.log(res)
// 寫文件,writeFileSync第一個(gè)參數(shù)是要寫入的文件路徑蛆橡,文件沒有的話會(huì)自動(dòng)創(chuàng)建掘譬,
//第二個(gè)參數(shù)是我們想要寫入的值
//第二個(gè)參數(shù)我們寫代碼的時(shí)候定義的是對(duì)象,但是最終錄入的是字符串睦焕,所以需要進(jìn)行轉(zhuǎn)換
if (res.access_token) {
fs.writeFileSync(fileName, JSON.stringify({
access_token: res.access_token,
createTime: new Date()
}))
}else{
// 如果因?yàn)榫W(wǎng)絡(luò)原因靴拱,一次獲取token失敗也必須再次獲取袜炕,因?yàn)楹竺娴乃胁僮鞫家蕾囘@個(gè)token
updateAccessToken()
}
}
// 封裝讀取token的方法
const getAccessToken = async ()=>{
try {
// 讀取文件
// 第二個(gè)參數(shù)utf8如果不傳,則默認(rèn)讀取的是二進(jìn)制數(shù)
const readRes = fs.readFileSync(fileName, 'utf8')
const readObj = JSON.parse(readRes)
console.log(readObj)
} catch (error) {
// 如果讀取失敗乌助,就重新請(qǐng)求接口
await updateAccessToken()
// 然后再去獲取token信息
await getAccessToken()
}
}
// updateAccessToken()
getAccessToken()
module.exports = getAccessToken
設(shè)置一個(gè)定時(shí)器陌知,去獲取token
setInterval(()=>{
await updateAccessToken()
},7200*1000)
路由規(guī)劃
下載安裝koa-router
npm install koa-router
新建controller文件夾仆葡,表示項(xiàng)目中C層(MVC模式),把前端發(fā)送過來的請(qǐng)求把篓,我們進(jìn)行云函數(shù)調(diào)用處理后再返還給前端=>這個(gè)文件夾的作用
在controller文件夾中新建一個(gè)playlist.js,關(guān)于歌單的處理寫在這個(gè)文件中
此時(shí)的app.js代碼
const Koa = require('koa')
const app = new Koa()
const Router = require('koa-router')
const router = new Router()
const playlist = require('./controller/playlist.js')
// 通過router聲明路由名稱, 對(duì)應(yīng)的就是playlist里面的路由
router.use('/playlist', playlist.routes())
// 聲明router
app.use(router.routes())
// 允許方法的調(diào)用
app.use(router.allowedMethods())
app.use(async (ctx) => {
ctx.body = 'hello world'
})
app.listen(3000, () => {
console.log('listening on 3000')
})
playlist.js代碼
const Router = require('koa-router')
const router = new Router()
router.get('/list',async(ctx,next)=>{
// 查詢歌單列表
ctx.body='歌單列表'
})
module.exports = router
啟動(dòng)項(xiàng)目皇耗,訪問localhost:3000/playlist/list,我們就能看到“歌單列表”
接下來万伤,在playlist.js中調(diào)用HTTP API觸發(fā)云函數(shù)
這一步敌买,我們實(shí)現(xiàn)訪問localhost:3000/playlist/list可以把請(qǐng)求到的歌單信息展現(xiàn)到瀏覽器上,此時(shí)的playlist.js完整代碼如下
const Router = require('koa-router')
const router = new Router()
const getAccessToken = require('../utils/getAccessToken.js')
const ENV = 'test-t1x7t'
const rp = require('request-promise')
router.get('/list', async (ctx, next) => {
const access_token = await getAccessToken()
// 查詢歌單列表
const url = `https://api.weixin.qq.com/tcb/invokecloudfunction?access_token=${access_token}&env=${ENV}&name=music`
// 用request-promise發(fā)送post請(qǐng)求的方式:定義一個(gè)options對(duì)象,然后將options作為發(fā)送請(qǐng)求的參數(shù)
const options = {
method: 'POST',
url: url,
body: {
// 首先我們需要告訴云函數(shù)中的tcb-router聋庵,我們要請(qǐng)求的具體路由
$url: 'playlist',
start: 0,
count: 50
},
json: true
}
ctx.body = await rp(options)
.then((res) => {
// console.log(res)
return JSON.parse(res.resp_data).data
})
.catch((err) => {
console.log("出錯(cuò)了")
})
})
module.exports = router
接下來我們要實(shí)現(xiàn)從前端項(xiàng)目發(fā)送請(qǐng)求到后端拿取這個(gè)json歌單列表數(shù)據(jù)
前端代碼部分1.30左右
解決跨域的方案之一:cors
在后端項(xiàng)目中配置上允許發(fā)請(qǐng)求的域名
首先需要在后端項(xiàng)目安裝corsnpm install koa2-cors
然后在app.js文件中進(jìn)行導(dǎo)入const cors = require('koa2-cors')
進(jìn)行配置
app.use(cors({
origin:['http://localhost:9528'],
credentials:true
}))
這樣的話祭玉,我們就可以從http://localhost:9528發(fā)送請(qǐng)求了春畔,origin的值是個(gè)數(shù)組,可以配置多個(gè)振峻。