前言:css
咱們在作移動端的點餐程序的時候,發現當菜品數量巨大的時候,特別是外加不少操做的時候(好比菜品半整份切換的時候)
,列表裏面的菜品數量 進行快速 加減和半整份切換就會卡頓。vue
那究竟是什麼讓手機如此卡頓呢?ios
我寫了個用例,用了2277條數據(找不到性能差的手機,能夠適當增長數據量來測試)
在 紅米3(
安卓版本:5.1.1 LMY47V)
上作了個實驗。c++
Normal.vue爲普通暴力渲染模式,Optimize.vue優化後的模式;git
demo 地址:github.com/trsoliu/vue…es6
1.發生的緣由:github
當咱們拿一個數組list用v-for直接把數組裏的對象渲染到頁面上的時候,其實,已經爲後續的性能埋下了雷。sql
Normal.vuenpm
<template>
<div class="normal">
普通列表
<ul>
<li v-for="(item,index) in list">
<img :src="item.img" />
<div class="left_bottom" >
<p>{{item.name}}</p>
<p><span v-if="item.num > 0">{{item.num}}整份</span><span v-if="item.num > 0">{{item.num}}半份</span></p>
<span class="add btn" @click="add(index)">+</span>
<span class="num">{{item.num}}</span>
<span class="reduce btn" @click="reduce(index)">-</span>
</div>
</li>
</ul>
</div>
</template>
<script>
import list from "./list.js"
export default {
name: 'normal',
data() {
return {
list: list
}
},
methods: {
add(index) {
let t = this;
console.log(index, "+");
t.list[index].num++;
},
reduce(index) {
let t = this;
t.list[index].num > 0 ? t.list[index].num-- : 0;
}
}
}
</script>複製代碼
在這裏,每次觸發➕或者➖來操做菜品數據時,都須要操做原list數組。api
每次操做完原數組後,原數組list發生變化,會從新走一遍v-for進行頁面重繪渲染(即便官方有跟蹤每一個節點的標識key,作重用和從新排序現有元素)
,那其實這個過程在少許數據的時候沒什麼影響,vue的速度很快。
但當用戶的手機是那種300-1000塊的街機或者系統老舊的時候,這裏的性能問題就尤其的明顯了;你會發現快速操做菜品加減的時候,菜品數字變化會緩慢或者直接跳值(好比直接從2變成5)
,同時你滑動頁面的時候頁面滾動也是卡頓的,由於這個時候頁面在渲染,滾動條也會短期停滯;
海量數據下,這種用戶體驗十分的糟糕,而且爲我發現市場大部分的列表操做都有這類的問題。
2.解決辦法
寫一個單獨的組件,將數組list中的每個對象傳給子組件(Operate.vue)
,組件用props接受到後,以後只操做傳過來的這個對象,不改變原數組list中的任何值;
備註:這裏爲將一個數組變爲兩個,一個爲 listOriginal 僅作初次渲染使用,另一個listOperate 在組件回調後操做,用來作渲染以外的業務處理。這樣頁面渲染和業務操做經過子組件達到互補干擾的效果,頁面也會極其流暢了。
如下紅框爲單獨組件渲染結果:
父組件:Optimize.vue
<template>
<div class="optimize">
優化列表
<ul>
<Operate v-for="(item,index) in listOriginal" :item="item" :index="index" :key="index"></Operate>
</ul>
</div>
</template>
<script>
import list from "./list.js"
export default {
name: 'optimize',
data() {
return {
listOriginal: JSON.parse(JSON.stringify(list)),//僅作初次渲染使用
listOperate:JSON.parse(JSON.stringify(list))//組件回調後操做,用來作渲染以外的業務處理
}
},
components:{
Operate: function(resolve) {
require(['@/components/Operate.vue'], resolve)
}
}
}
</script>複製代碼
子組件:Operate.vue
<template>
<li class="operate">
<img :src="item.img" />
<div class="left_bottom">
<p>{{item.name}}</p>
<p><span v-if="item.num > 0">{{item.num}}整份</span><span v-if="item.num > 0">{{item.num}}半份</span></p>
<span class="add btn" @click="add(index)">+</span>
<span class="num">{{item.num}}</span>
<span class="reduce btn" @click="reduce(index)">-</span>
</div>
</li>
</template>
<script>
export default {
name: 'operate',
data() {
return {}
},
props: ["item", "index"],
methods: {
add(index) {
let t = this;
t.item.num++;
//t.$emit(...);//回調操做父組件listOperate,或者處理其餘業務都可
},
reduce(index) {
let t = this;
t.item.num > 0 ? t.item.num-- : 0;
//t.$emit(...);//回調操做父組件listOperate,或者處理其餘業務都可
}
}
}
</script>複製代碼
經過改變數據的使用方式,和合理利用框架,達到性能的優化。
以上大概就是我寫的用例的基本對比狀況,若是疑問能夠留言給我或者加羣,我都會一一解答的。
有問題能夠加羣交流535798405;
demo 地址:github.com/trsoliu/vue…