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…

相关文章
相关标签/搜索