最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

mpvue性能優(yōu)化實戰(zhàn)技巧(小結(jié))

 更新時間:2019年04月17日 11:33:16   作者:fengxianqi  
這篇文章主要介紹了mpvue性能優(yōu)化實戰(zhàn)技巧(小結(jié)),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

最近一直在折騰mpvue寫的微信小程序的性能優(yōu)化,分享下實戰(zhàn)的過程。

先上個優(yōu)化前后的圖:


可以看到打包后的代碼量從813KB減少到387KB,Audits體驗評分從BA,效果還是比較明顯的。其實這個指標(biāo)說明不了什么,而且輕易就可以做到,更重要的是優(yōu)化小程序運行過程中的卡頓感,請耐心往下看。

常規(guī)優(yōu)化

常規(guī)的Web端優(yōu)化方法在小程序中也是適用的,而且不可忽視。

一、壓縮圖片

這一步最簡單,但是容易被忽視。在tiny上在線壓縮,然后下載替換即可。


我這項目的壓縮率高達72%,可以說打包后的代碼從813KB降到387KB大部分都是歸功于壓縮圖片了。

二、移除無用的庫

我之前在項目中使用了Vant Weapp,在static目錄下引入了整個庫,但實際上我只使用了button,field,dialog等幾個組件,實在是沒必要。

所以干脆移除掉了,微信小程序自身提供的button,wx.showModal等一些組件基本可以滿足需求,自己手寫一下樣式也不用花什么時間。

在這里建議大家,在微信小程序中,盡量避免使用過多的依賴庫

不要貪圖方便而引入一些比較大的庫,小程序不同于Web,限制比較多,能自己寫一下就盡量自己寫一下吧。

小程序的優(yōu)化

咱們首先得看一下官方優(yōu)化建議,大多是圍繞這個建議去做。

一、開啟Vue.config._mpTrace = true

這個是mpvue性能優(yōu)化的一個黑科技啊,可能大多數(shù)同學(xué)都不知道這個,我在官方文檔都沒有搜到到這個配置,我真的是服了。

我能找到這個配置也是Google機緣巧合下看到的,出處:mpvue重要更新,頁面更新機制進行全面升級
具體做法是在/src/main.js添加Vue.config._mpTrace = true,如:

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

添加了Vue.config._mpTrace屬性,這樣就可以看到console里會打印每500ms更新的數(shù)據(jù)量。如圖:


如果數(shù)據(jù)更新量很大,會明顯感覺小程序運行卡頓,反之就流暢。因此我們可以根據(jù)這個指標(biāo),逐步找出性能瓶頸并解決掉。

二、精簡data

1. 過濾api返回的冗余數(shù)據(jù)

后端的api可能是需要同時為iOS,Android,H5等提供服務(wù)的,往往會有些冗余的數(shù)據(jù)小程序是用不到的。比如api返回的一個文章列表數(shù)據(jù)有很多字段:

this.articleList = [
  {
    articleId: 1,
    desc: 'xxxxxx',
    author: 'fengxianqi',
    time: 'xxx',
    comments: [
      {
        userId: 2,
        conent: 'xxx'
      }
    ]
  },
  {
    articleId: 2
    // ...
  },
  // ...
]

假設(shè)我們在小程序中只需要用到列表中的部分字段,如果不對數(shù)據(jù)做處理,將整個articleListsetData進去,是不明智的。

小程序官方文檔:單次設(shè)置的數(shù)據(jù)不能超過1024kB,請盡量避免一次設(shè)置過多的數(shù)據(jù)。

可以看出,內(nèi)存是很寶貴的,當(dāng)articleList數(shù)據(jù)量非常大超過1M時,某些機型就會爆掉(我在iOS中遇到過很多次)。

因此,需要將接口返回的數(shù)據(jù)剔除掉不需要的,再setData,回到我們上面的articleList例子,假設(shè)我們只需要用articleIdauthor這兩個字段,可以這樣:

import { getArticleList } from '@/api/article'
export default {
  data () {
    return {
      articleList: []
    }
  }
  methods: {
    getList () {
      getArticleList().then(res => {
        let rawList = res.list
        this.articleList = this.simplifyArticleList(rawList)
      })
    },
    simplifyArticleList (list) {
      return list.map(item => {
        return {
          articleId: item.articleId,
          author: item.author
          // 需要哪些字段就加上哪些字段
        }
      })
    }
  }
}

這里我們將返回的數(shù)據(jù)通過simplifyArticleList 來精簡數(shù)據(jù),此時過濾后的articleList中的數(shù)據(jù)類似:

[
  {articleId: 1, author: 'fengxianqi'},
  {articleId: 2, author: 'others'}
  // ...
]

當(dāng)然,如果你的需求中是所有數(shù)據(jù)都要用到(或者大部分?jǐn)?shù)據(jù)),就沒必要做一層精簡了,收益不大。畢竟精簡數(shù)據(jù)的函數(shù)中具體的字段,是會增加維護成本的。

PS: 在我個人的實際操作中,做數(shù)據(jù)過濾雖然增加了維護的成本,但一般收益都很大,因次這個方法比較推薦。

2. data()中只放需要的數(shù)據(jù)

import xx from 'xx.js'
export default {
  data () {
    return {
      xx,
      otherXX: '2'
    }
  }
}

有些同學(xué)可能會習(xí)慣將import的東西都先放進data中,再在methods中使用,在小程序中可能是個不好的習(xí)慣。

因為通過Vue.config._mpTrace = true在更新某個數(shù)據(jù)時,我對比放進data和不放進data中的兩種情況會有差別。

所以我猜測可能是data是會一起更新的,比如只是想更新otherXX時,會同時將xx也一起合起來setData了。

3. 靜態(tài)圖片放進static

這個問題和上面的問題其實是一樣的,有時候我們會通過import的方式引入,比如這樣:

<template>
  <img :src="UserIcon">
</template>
<script>
import UserIcon from '@/assets/images/user_icon.png'
export default {
  data () {
    return {
      UserIcon
    }
  }
}
</script>

這樣會導(dǎo)致打包后的代碼,圖片是base64形式(很長的一段字符串)存放在data中,不利于精簡data。同時當(dāng)該組件多個地方使用時,每個組件實例都會攜帶這一段很長的base64代碼,進一步導(dǎo)致數(shù)據(jù)的冗余。

因此,建議將靜態(tài)圖片放到static目錄下,這樣引用:

<template>
  <img src="/static/images/user_icon.png">
</template>

代碼也更簡潔清爽。

看一下做了上面操作的前后對比圖,使用體驗上也流暢了很多。

三、swiper優(yōu)化

小程序自身提供的swiper組件性能上不是很好,使用時要注意。參考著兩個思路:

【優(yōu)化】解決swiper渲染很多圖片時的卡頓

想請教一下小程序swiper組件的問題

在我使用時,由于需求原因,動態(tài)刪掉swiper-item的思路不可行(手滑時會造成抖動)。因此只能作罷。但仍然可以優(yōu)化一下:

將未顯示的swiper-item中的圖片用v-if隱藏到,當(dāng)判斷到current時才顯示,防止大量圖片的渲染導(dǎo)致的性能問題。

四、vuex使用注意事項

我之前寫過的一篇mpvue開發(fā)音頻類小程序踩坑和建議里面有講如何在小程序中使用vuex。但遇到了個比較嚴(yán)重的性能問題。

1. 問題描述

我開發(fā)的是一個音頻類的小程序,所以需要將播放列表playList,當(dāng)前索引currentIndex和當(dāng)前時長currentTime放進state.js中:

const state = {
 currentIndex: 0, // playList當(dāng)前索引
 currentTime: 0, // 當(dāng)前播放的進度
 playList: [], // {title: '', url: '', singer: ''}
}

每次用戶點擊播放音頻時,都會先加載音頻的播放列表playList,然后播放時更新當(dāng)前時長currentTime,發(fā)現(xiàn)有時候播音頻時整個小程序非??D。

注意到,音頻需每秒就得更新一次currentTime,即每秒就做一次setData操作,稍微有些卡頓是可以理解的。但我發(fā)現(xiàn)是播放列表數(shù)據(jù)比較多時會特別卡,比如playList的長度是100條以上時。

2. 問題原因

我開啟Vue.config._mpTrace = true后發(fā)現(xiàn)一個規(guī)律:

當(dāng)palyList數(shù)據(jù)量小時,console顯示造成的數(shù)據(jù)量更新數(shù)值比較小;當(dāng)playList比較大時,console顯示造成的數(shù)據(jù)量更新數(shù)值比較大。

PS: 我曾嘗試將playList數(shù)據(jù)量增加到200條,每500ms的數(shù)據(jù)量更新達到800KB左右。

到這里基本可以確定一個事實就是:更新state中的任何一個字段,將導(dǎo)致整個state全量一起setData。在我這里的例子,雖然我每次只是更新currentTime這個字段的值,但依然導(dǎo)致將state中的其他字段如playList,currentIndex都一起做了一次setData操作。

3. 解決問題

有兩個思路:

精簡state中保存的數(shù)據(jù),即限制playList的數(shù)據(jù)不能太多,可將一些數(shù)據(jù)暫存在storage

vuex采用Module的寫法能改善這個問題,雖然使用時命名空間造成一定的麻煩。vuex傳送門

一般情況下,推薦使用后者。我在項目中嘗試使用了前者,同樣能達到很好的效果,請繼續(xù)看下面的分享。

五、善用storage

1.為什么說要善用storage

由于小程序的內(nèi)存非常寶貴,占用內(nèi)存過大會非常卡頓,因此最好盡可能少的將數(shù)據(jù)放到內(nèi)存中,即vuex存的數(shù)據(jù)要盡可能少。而小程序的storage支持單個 key允許存儲的最大數(shù)據(jù)長度為 1MB,所有數(shù)據(jù)存儲上限為 10MB。

所以可以將一些相對取用不頻繁的數(shù)據(jù)放進storage中,需要時再將這些數(shù)據(jù)放進內(nèi)存,從而緩解內(nèi)存的緊張,有點類似Windows中虛擬內(nèi)存的概念。

2.storage換內(nèi)存的實例

這個例子講的會有點啰嗦,真正能用到的朋友可以詳細(xì)看下。

上面講到playList數(shù)據(jù)量太多,播放一條音頻時其實只需要最多保證3條數(shù)據(jù)在內(nèi)存中即可,即上一首播放中的,下一首,我們可以將多余的播放列表存放在storage中。

PS: 為了保證更平滑地連續(xù)切換下一首,我們可以稍微保存多幾條,比如我這里選擇保存5條數(shù)據(jù)在vuex中,播放時始終保證當(dāng)前播放的音頻前后都有兩條數(shù)據(jù)。
// 首次播放背景音頻的方法
async function playAudio (audioId) {
  // 拿到播放列表,此時的playList最多只有5條數(shù)據(jù)。getPlayList方法看下面
  const playList = await getPlayList(audioId)
  // 當(dāng)前音頻在vuex中的currentIndex
  const currentIndex = playList.findIndex(item => item.audioId === audioId)
  
  // 播放背景音頻
  this.audio = wx.getBackgroundAudioManager()
  this.audio.title = playList[currentIndex].title
  this.audio.src = playList[currentIndex].url
  
  // 通過mapActions將播放列表和currentIndex更新到vuex中
  this.updateCurrentIndex(index) 
  this.updatePlayList(playList) 
  // updateCurrentIndex和updatePlayList是vuex寫好的方法
}

// 播放音頻時獲取播放列表的方法,將所有數(shù)據(jù)存在storage,然后返回當(dāng)前音頻的前后2條數(shù)據(jù),保證最多5條數(shù)據(jù)
import { loadPlayList } from '@/api/audio'
async function getPlayList (courseId, currentAudioId) {
  // 從api中請求得到播放列表
  // loadPlayList是api的方法, courseId是獲取列表的參數(shù),表示當(dāng)前課程下的播放列表
  let rawList = await loadPlayList(courseId)
  // simplifyPlayList過濾掉一些字段
  const list = this.simplifyPlayList(rawList)
  // 將列表存到storage中
  wx.setStorage({
    key: 'playList',
    data: list
  })
  return subPlayList(list, currentAudioId)
}

重點是subPlayList方法,這個方法保證了拿到的播放列表是最多5條數(shù)據(jù)。

function subPlayList(playList, currentAudioId) {
 let tempArr = [...playList]
 const count = 5 // 保持vuex中最多5條數(shù)據(jù)
 const middle = parseInt(count / 2) // 中點的索引
 const len = tempArr.length
 // 如果整個原始的播放列表本來就少于5條數(shù)據(jù),說明不需要裁剪,直接返回
 if (len <= count) {
  return tempArr
 }
 // 找到當(dāng)前要播放的音頻的所在位置
 const index = tempArr.findIndex(item => item.audioId === currentAudioId)
 // 截取當(dāng)前音頻的前后兩條數(shù)據(jù)
 tempArr = tempArr.splice(Math.max(0, Math.min(len - count, index - middle)), count)
 return tempArr
}

tempArr.splice(Math.max(0, index - middle), count)可能有些同學(xué)比較難理解,需要仔細(xì)琢磨一下。假設(shè)playList有10條數(shù)據(jù):

  • 當(dāng)前音頻是列表中的第1條(索引是0),截取前5個:playList.splice(0, 5),此時currentAudio在這5個數(shù)據(jù)的索引是0,沒有上一首,有4個下一首
  • 當(dāng)前音頻是列表中的第2條(索引是1),截取前5個:playList.splice(0, 5),此時currentAudio在這5個數(shù)據(jù)的索引是1,有1個上一首,3個下一首
  • 當(dāng)前音頻是列表中的第3條(索引是2),截取前5個:playList.splice(0, 5),此時currentAudio在這5個數(shù)據(jù)的索引是2,有2個上一首,2個下一首
  • 當(dāng)前音頻是列表中的第4條(索引是3),截取第1到6個:playList.splice(1, 5)
  • ,此時currentAudio在這5個數(shù)據(jù)的索引是2,有2個上一首,2個下一首
  • 當(dāng)前音頻是列表中的第5條(索引是4),截取第2到7個:playList.splice(2, 5),此時currentAudio在這5個數(shù)據(jù)的索引是2,有2個上一首,2個下一首
  • ...
  • 當(dāng)前音頻是列表中的第9條(索引是8),截取后5個:playList.splice(4, 5),此時currentAudio在這5個數(shù)據(jù)的索引是3,有3個上一首,1個下一首
  • 當(dāng)前音頻是列表中的最后1條(索引是9),截取后的5個:playList.splice(4, 5),此時currentAudio在這5個數(shù)據(jù)的索引是4,有4個上一首,沒有下一首

有點啰嗦,感興趣的同學(xué)仔細(xì)琢磨下,無論當(dāng)前音頻在哪,都始終保證了拿到當(dāng)前音頻前后的最多5條數(shù)據(jù)。

接下來就是維護播放上一首或下一首時保證當(dāng)前vuex中的playList始終是包含當(dāng)前音頻的前后2條。

播放下一首

function playNextAudio() {
  const nextIndex = this.currentIndex + 1
  if (nextIndex < this.playList.length) {
    // 沒有超出數(shù)組長度,說明在vuex的列表中,可以直接播放
    this.audio = wx.getBackgroundAudioManager()
    this.audio.src = this.playList[nextIndex].url
    this.audio.title = this.playList[nextIndex].title
    this.updateCurrentIndex(nextIndex)
    // 當(dāng)判斷到已經(jīng)到vuex的playList的邊界了,重新從storage中拿數(shù)據(jù)補充到playList
    if (nextIndex === this.playList.length - 1 || nextIndex === 0) {
     // 拿到只有當(dāng)前音頻前后最多5條數(shù)據(jù)的列表
     const newList = getPlayList(this.playList[nextIndex].courseId, this.playList[nextIndex].audioId)
     // 當(dāng)前音頻在這5條數(shù)據(jù)中的索引
     const index = newList.findIndex(item => item.audioId === this.playList[nextIndex].audioId)
     // 更新到vuex
     this.updateCurrentIndex(index)
     this.updatePlayList(newList)
    }
  }
}

這里的getPlayList方法是上面講過的,本來是從api中直接獲取的,為了避免每次都從api直接獲取,所以需要改一下,先讀storage,若無則從api獲?。?/p>

import { loadPlayList } from '@/api/audio'
async function getPlayList (courseId, currentAudioId) {
  // 先從緩存列表中拿
  const playList = wx.getStorageSync('playList')
  if (playList && playList.length > 0 && courseId === playList[0].courseId) {
   // 命中緩存,則從直接返回
   return subPlayList(playList, currentAudioId)
  } else {
   // 沒有命中緩存,則從api中獲取
   const list = await loadPlayList(courseId)
   wx.setStorage({
    key: 'playList',
    data: list
   })
   return subPlayList(list, currentAudioId)
  }
}

播放上一首也是同理,就不贅述了。

PS: 將vuex中的數(shù)據(jù)精簡后,我所做的小程序在播放音頻時刷其他頁面已經(jīng)非常流暢啦,效果非常好。

六、動畫優(yōu)化

這個問題在mpvue開發(fā)音頻類小程序踩坑和建議已經(jīng)講過了,感興趣的可以移步看一眼,這里只寫下概述:

如果要使用動畫,盡量用css動畫代替wx.createAnimation使用css動畫時建議開啟硬件加速最后

大致總結(jié)一下上面所講的幾個要點:

  • 開發(fā)時打開Vue.config._mpTrace = true。
  • 謹(jǐn)慎引入第三方庫,權(quán)衡收益。
  • 添加數(shù)據(jù)到data中時要克制,能精簡盡量精簡。
  • 圖片記得要壓縮,圖片在顯示時才渲染。
  • vuex保持?jǐn)?shù)據(jù)精簡,必要時可先存storage。

性能優(yōu)化是一個永不止步的話題,我也還在摸索,不足之處還請大家指點和分享。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Vue3中的script?setup語法糖的使用及說明

    Vue3中的script?setup語法糖的使用及說明

    在這篇博客中,我們將探討?script?setup?的含義、好處以及示例代碼,幫助你更好地理解并在項目中合理運用這一特性,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • 在Vant的基礎(chǔ)上封裝下拉日期控件的代碼示例

    在Vant的基礎(chǔ)上封裝下拉日期控件的代碼示例

    這篇文章主要介紹了在Vant的基礎(chǔ)上封裝下拉日期控件的代碼示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-12-12
  • VUE中watch的詳細(xì)使用教程(推薦!)

    VUE中watch的詳細(xì)使用教程(推薦!)

    這篇文章主要給大家介紹了關(guān)于VUE中watch的詳細(xì)使用教程,watch是vue實例的一個屬性,主要用來監(jiān)聽數(shù)據(jù)的變化,并做出一些操作,需要的朋友可以參考下
    2023-08-08
  • vue如何通過button的disabled控制按鈕能否被使用

    vue如何通過button的disabled控制按鈕能否被使用

    這篇文章主要介紹了vue如何通過button的disabled控制按鈕能否被使用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • vue同一個瀏覽器登錄不同賬號數(shù)據(jù)覆蓋問題解決方案

    vue同一個瀏覽器登錄不同賬號數(shù)據(jù)覆蓋問題解決方案

    同一個瀏覽器登錄不同賬號session一致,這就導(dǎo)致后面登錄的用戶數(shù)據(jù)會把前面登錄的用戶數(shù)據(jù)覆蓋掉,這個問題很常見,當(dāng)前我這邊解決的就是同一個瀏覽器不同窗口只能登錄一個用戶,對vue同一個瀏覽器登錄不同賬號數(shù)據(jù)覆蓋問題解決方法感興趣的朋友一起看看吧
    2024-01-01
  • vue使用WebSocket模擬實現(xiàn)聊天功能

    vue使用WebSocket模擬實現(xiàn)聊天功能

    這篇文章主要介紹了vue使用WebSocket模擬實現(xiàn)聊天功能,通過創(chuàng)建node服務(wù)和server.js文件實例代碼相結(jié)合給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2021-08-08
  • ant?design?vue的form表單取值方法

    ant?design?vue的form表單取值方法

    這篇文章主要介紹了ant?design?vue的form表單取值方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • React/vue開發(fā)報錯TypeError:this.getOptions?is?not?a?function的解決

    React/vue開發(fā)報錯TypeError:this.getOptions?is?not?a?function

    這篇文章主要給大家介紹了關(guān)于React/vue開發(fā)報錯TypeError:this.getOptions?is?not?a?function的解決方法,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-07-07
  • 帶你一文了解Vue生命周期鉤子

    帶你一文了解Vue生命周期鉤子

    生命周期鉤子又被叫做生命周期時間,生命周期函數(shù),生命周期鉤子就是vue生命周期中出發(fā)的各類事件,這些事件被稱為生命周期鉤子,下面這篇文章主要給大家介紹了關(guān)于Vue生命周期鉤子的相關(guān)資料,需要的朋友可以參考下
    2022-06-06
  • vue+openlayers+nodejs+postgis實現(xiàn)軌跡運動效果

    vue+openlayers+nodejs+postgis實現(xiàn)軌跡運動效果

    使用postgres(postgis)數(shù)據(jù)庫以及nodejs作為后臺,vue和openlayers做前端,openlayers使用http請求通過nodejs從postgres數(shù)據(jù)庫獲取數(shù)據(jù),這篇文章主要介紹了vue+openlayers+nodejs+postgis實現(xiàn)軌跡運動,需要的朋友可以參考下
    2024-05-05

最新評論

甘洛县| 文成县| 龙州县| 章丘市| 鹤山市| 天等县| 清苑县| 恩施市| 蓝山县| 思茅市| 正蓝旗| 樟树市| 蕲春县| 黎川县| 抚顺县| 中宁县| 曲周县| 普定县| 根河市| 临清市| 锡林郭勒盟| 灵川县| 简阳市| 内乡县| 集贤县| 丹寨县| 阜新市| 松潘县| 新闻| 全州县| 嵩明县| 湛江市| 葵青区| 修武县| 芦山县| 长阳| 莱西市| 南宁市| 缙云县| 临沭县| 安徽省|