vue海量數據列表操做的性能優化,渣渣手機性能一秒變絲滑!

前言: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…

相關文章
相關標籤/搜索