需求分析

需求:根据后端返回的字段,生成多条表单数据( 实质是批量发布商品 ),预留可增删改功能

实现思路

后端返回的数据格式是一个一维数组(一个商品的所有字段)

let product_item =  [
	{
	  prop:'name',
	  value:'',
	  type:'input',//表单类型--输入框
	},
	{
	  prop:'img',
	  value:'',
	  type:'img'//表单类型--图片
	},
	{
	  prop:'type',
	  value:'',
	  type:'select'//表单类型--下拉框
	},
	{
	  prop:'type',
	  value:'',
	  type:'selectSearch'//表单类型--下拉搜索
	}
	...
]

这是一个商品的,可以直接通过遍历生成表单就行,那么现在我们的需求是发布多个商品的,需要进行一个处理,也就是变成二维数组

product_list = [
	product_item,
	product_item,
	...
]

这一步需要注意的是,每一个product_item里面的字段的引用位置不能相同,否则输入表单时会相互映射,所以每一个product_item都做一个深拷贝。

写法一
代码集中在一个组件里面,我想大多数人第一遍写的代码大多数是这样的,这样子写也并不是错的,但是表单的量一多(product_list)就会出现卡顿现象,比如输入、下拉的时候,在测试过程中,10个商品卡顿现象还不明显,当增加到30-100条时就非常卡顿了,甚至不能使用。至于卡顿的原因往后看

	<div v-for="(row,i) in product_list " :key="i">
		<div v-for="(v,k) in row" :key="k">
			<div v-if="v.type==='input'">
				<el-input></el-input>
			</div>
			<div v-else-if="xxx"></div>
			....
		</div>
	</div>

写法二
将代码拆分成多个组件,将表单换为原生的表单(样式采用element ui的)
product.vue页面
渲染多条商品表单的

	<div v-for="(row,i) in product_list " :key="i">
		<product-item :row="row" :index="i"></product-item>//每一条商品表单组件
	</div>

product-item组件
渲染单个商品表单的

<div v-for="(item,i) in row" :key="i">
	<product-item-form :item="item"></product-item-form>
</div>

product-item-form组件
根据类型渲染表单,此处使用了:lazy修饰符避免频繁更新,以提高流畅度

<div>
	<div v-if="item.type==='input'">
		<input v-model.lazy="item[item.prop]" />//绑定到prop上,使用原生标签,性能翻倍
	</div>
	<div v-else-if="xxx"></div>
	...
</div>

由于item的引用位置依然是product_list的,所以不必担心拿不到最终的值的问题。

利用方法二的写法进行测试
测试的发布于商品个数100个,总的表单的个数100*11 = 1100(相当于1100个输入框),结果是输入不卡,下拉框也不卡,整体流畅,与写法一差距的性能巨大。

在这里插入图片描述

总结

也许在少量表单时(20个以内)的时候,俩者差距不大,但是当超过30个商品时就差距很大。
优化点:

  1. 拆分组件,在组件更新的时候只需要更新组件,而不用整个页面,这跟vue的patch虚拟dom效率有关
  2. 使用lazy修饰符,避免输入更新data太频繁造成卡顿,这个相当于节流吧…
  3. 其实UI框架封装的太臃肿,缝合了各种功能,初始化的时间长,判断条件多等等,所以尽量使用原生的标签,性能强上好几倍(样式可以直接copy UI框架的)。

存在的问题: 因为渲染的数据量多,如果一次性加载100条,页面初次加载的时候会有点慢(渲染慢),我个人认为最好的方法还是分步加载,一次加载30-40条,当用户滚动到一定的位置再追加30-40条,以此类推。如果大家有更好的优化方法,欢迎在评论区讨论。

Logo

前往低代码交流专区

更多推荐