vue性能优化方法有哪些,vue前端优化
演示代码是用Vue3 ts Vite写的,但也列出了适用于Vue2的优化技术,有一定的参考价值。感兴趣的朋友可以参考一下。
目录
代码优化
使用v-for键
使用v-if/v-else-if/v-else中的key合理选择v-if和v-show。
使用简单计算属性功能组件(Vue2)拆分组件
使用局部变量
使用保持活动状态
事件的破坏
图片加载
采用合理的数据处理算法。
其他的
屏幕/音量优化
优化的体积代码分段
网络
演示代码是用Vue3 ts Vite写的,但也将列出适用于Vue2的优化技术。如果一个优化只适用于Vue3或Vue2,我会在标题中把它标出来。
代码优化
v-for 中使用 key
使用v-for更新渲染元素列表时,默认使用原地复用策略;当列表被修改时,他会根据键值判断某个值是否被修改。如果修改了,会重新渲染;否则,前面的元素将被重用。
使用钥匙的注意事项:
不要使用可能重复或可能改变的键值(控制台也会给出提醒)
不要使用数组的索引作为键值,因为如果一个元素被插入到数组中,它后面的元素的索引会改变。
如果数组中没有唯一的键值,请考虑向其中添加一个键字段。Symbol()的值可以保证唯一性。
v-if/v-else-if/v-else 中使用 key
很多人可能忽略了这一点。
原因:默认情况下,Vue会尽可能高效地更新DOM。这意味着当它在相同类型的元素之间切换时,它将修补现有的元素,而不是删除旧的元素,然后在相同的位置添加一个新元素。如果不同的元素被识别为相同的,就会出现意想不到的副作用。
如果只有一个v-if,而没有v-else或v-if-else,则不需要添加key。
与v-for的key相比,v-if/v-else-if/v-else中的key相对简单,我们可以直接写一个固定的字符串或者数组。
过渡
按钮
v-if=isEditing
v-on:click=isEditing=false
救援
/按钮
按钮
v-否则
v-on:click=isEditing=true
编辑
/按钮
/过渡。v-enter-active,v-离开-活动{
过渡:全1;
}。回车。v-离开到{
不透明度:0;
transform:translate y(30px);
}。v-离开-活动{
位置:绝对;
}
比如上面的代码,你会发现虽然按钮上加了转场效果,但是不加按键开关是无法触发转场的。
V-for和v-if不应一起使用(Vue2)
这种优化技术仅限于调整Vue2和Vue3中v-for和v-if的优先级。
这个大家都知道。
不要在同一个元素上同时使用v-if和v-for。Vue2.x风格指南指南
原因是v-for的优先级高于v-if,所以当它们用在同一个标签上时,每次渲染都会先循环,再进行条件判断。
注意:Vue3中v-if的优先级高于v-for,所以当v-for和v-if一起使用时,效果类似于Vue2中提升v-if。
比如下面这段代码在Vue2中是不推荐的,Vue会给出相应的警告。
保险商实验所
li v-for=用户中的用户 v-if=user.active
{{用户名}}
/李
/ul
我们应该尽力将v-if移到更高的级别,或者使用计算属性来处理数据。
ul v-if=active
li v-for=用户中的用户
{{用户名}}
/李
/ul
如果不希望循环内容有不必要的上级容器,那么可以选择使用template作为其父元素。浏览器不会将模板呈现为DOM节点。
如果我想判断遍历对象中每一项的内容来选择渲染数据,我可以使用computed来过滤遍历对象。
//js
let users active=computed(()=users . filter(user=user . active))
//模板
保险商实验所
Li v-for= users active中的用户
{{用户名}}
/李
/ul
合理的选择 v-if 和 v-show
v-if和v-show的区别大家都很熟悉;V-if通过直接操作DOM的删除和添加来控制元素的显示和隐藏;V-show通过控制DOM的显示CSS的熟悉程度来控制元素的显示和隐藏。
因为添加/删除DOM的性能远远低于操作DOM的CSS属性的性能
因此,当元素需要频繁显示/隐藏时,我们使用v-show来提高性能。
当元素不需要频繁的显示/隐藏变化时,我们可以通过v-if移除DOM,这样可以节省浏览器渲染这个DOM的一部分所需的资源。
使用简单的 计算属性
复杂的计算属性应该分成尽可能多的简单属性。
易于测试
当每个计算的属性都包含一个非常简单且很少依赖的表达式时,编写测试来确保它正确工作将会更容易。
易于阅读
简化计算属性要求您为每个值指定一个描述性名称,即使该名称不可重复使用。这使得其他开发人员(以及将来的您)更容易关注他们关心的代码,并弄清楚发生了什么。
更好地“拥抱变化”
任何可以命名的值都可以在视图中使用。例如,我们可能想要显示一条消息来告诉用户他们已经节省了多少钱;税也可以计算,但它们可以单独列出,而不是作为总价的一部分。
小的、专用的计算属性减少了信息使用的假设限制,所以当需求改变时不需要重构。
Vue2风格指南指南
Computed大家都很熟悉,当表达式中依赖的响应式数据发生变化时,它会重新计算。如果我们在一个计算属性中写一个更复杂的表达式,那么它所依赖的响应数据就会变得更加随意。当任何一个依赖关系改变时,整个表达式都需要重新计算。
让price=computed(()={
设基本价格=制造成本/(1 -利润率)
返回(
底价-
基本价格*(折扣百分比 0)
)
})
当制造商成本、利润率和折扣百分比中的任何一个发生变化时,将重新计算整个价格。
但是如果我们把它改成下面这样
设base price=computed(()=manufactureCost/(1-利润率))
let discount=computed(()=base price *(discount percent 0))
让final price=computed(()=base price-discount)
当discountPercent发生变化时,只会重新计算discount和finalPrice,但由于computed的缓存功能,不会重新计算basePrice。
functional 函数式组件(Vue2)
请注意,这仅用作Vue2中的一种优化方法。在3.x中,有状态组件和功能组件之间的性能差异已经大大减小,在大多数用例中可以忽略不计。所以在sfc上使用functional的开发者的迁移路径是删除这个属性,将props的所有引用重命名为$props,将attrs重命名为$attrs。
优化前
模板
div class=cell
div v-if=value class=on/div
第五节-else class= off /节
/div
/模板
脚本
导出默认值{
道具:[值],
}
/脚本
优化后
模板功能
div class=cell
div v-if= props . value class= on /div
第五节-else class= off /节
/div
/模板
脚本
导出默认值{
道具:[值],
}
/脚本
没有这个(没有实例)
没有响应数据。
拆分组件
什么?你写了1000多行代码的vue文件?
合理拆分组件不仅可以优化性能,还可以使代码更清晰,可读性更强。单一功能原则
起源于https://slides.com/akryum/vueconfus-2019#/4/0/3.
优化前
模板
div:style= { opacity:number/300 }
div{{ heavy() }}/div
/div
/模板
脚本
导出默认值{
道具:[数字],
方法:{
heavy () { /*繁重的任务*/}
}
}
/脚本
优化后
模板
div:style= { opacity:number/300 }
ChildComp/
/div
/模板
脚本
导出默认值{
道具:[数字],
组件:{
子组件:{
方法:{
heavy () { /*繁重的任务*/}
},
渲染(h) {
返回h(div ,this.heavy())
}
}
}
}
/脚本
因为Vue的更新是组件粒度的,虽然每一帧都是通过数据修改重新渲染的,但是ChildComp不会重新渲染,因为它内部没有响应的数据变化。因此,优化的组件不会在每次呈现时都执行耗时的任务。
使用局部变量
优化前
模板
div:style= { opacity:start/300 } { { result } }/div
/模板
脚本
从“@/utils”导入{ heavy }
导出默认值{
道具:[开始],
计算值:{
base () { return 42 },
结果(){
让结果=this.start
for(设I=0;i 1000i ) {
结果=重(this.base)
}
回送结果
}
}
}
/脚本
优化后
模板
div :style={ opacity: start/300 }
{{ result }}/div
/模板
脚本
从“@/utils”导入{ heavy }
导出默认值{
道具:[开始],
计算值:{
base () { return 42 },
结果(){
const base=this.base
让结果=this.start
for(设I=0;i 1000i ) {
结果=重(基础)
}
回送结果
}
}
}
/脚本
下面是优化前后组件的计算属性结果实现的区别。优化前的组件在计算过程中多次访问this.base,而优化后的组件在计算前使用局部变量base缓存this.base,然后直接访问base。
那么为什么这种差异会造成性能的差异呢?原因是每次访问this.base,因为this.base是一个响应式对象,它的getter会被触发,然后执行依赖集合的相关逻辑代码。类似的逻辑执行得更频繁。如示例中,数百个组件循环更新,每个组件触发计算的重新计算,然后依赖关系收集的相关逻辑被多次执行,因此性能自然下降。
从需求的角度来说,this.base执行一次依赖关系收集就足够了,将其getter求值结果返回给局部变量base,这样在再次访问base时就不会触发getter,也不会遵循依赖关系收集的逻辑,性能自然会得到提升。
来揭秘Vue.js的九大性能优化技巧
使用 KeepAlive
当一些渲染成本高的组件需要频繁切换时,可以使用keep-alive来缓存这个组件。
使用keep-alive后,keep-alive包装的组件的vnode和DOM会在第一次渲染后缓存,然后下一次组件再次渲染时,直接从缓存中获取对应的vnode和DOM,再进行渲染。不需要再经历组件初始化、渲染、补丁等一系列过程,减少了脚本的执行时间,性能更好。
注意:滥用keep-alive只会让你的应用更加卡顿,因为长时间占用更多内存。
事件的销毁
当一个组件被销毁时,我们应该清除组件中添加的全局事件和计时器,以防止内存泄漏。
Vue3的HOOK允许我们把事件的声明和销毁写在一起,可读性更强。
函数scrollFun(){ /*.*/}
document . addevent listener( scroll ,scrollFun)
onBeforeUnmount(()={
document . removeeventlistener( scroll ,scrollFun)
})
Vue2还是可以通过$once达到这个效果的。当然,你也可以在optionsAPI beforeDestroy中销毁事件,但我更倾向于前者的写法,因为后者会让同样功能的代码更加分散。
函数scrollFun(){ /*.*/}
document . addevent listener( scroll ,scrollFun)
这个。$once(hook:beforeDestroy ,()={
document . removeeventlistener( scroll ,scrollFun)
})
函数scrollFun(){ /*.*/}
导出默认值{
已创建(){
document . addevent listener( scroll ,scrollFun)
},
销毁前(){
document . removeeventlistener( scroll ,scrollFun)
}
}
图片加载
惰性图像加载:适用于页面上有很多图像,并且不能全部显示在一个屏幕上的情况。vue-lazyload插件为我们提供了一个方便的镜像惰性加载指令v-lazy。
但是,并不是所有的图片都适合懒人加载。比如横幅、相册等。更推荐使用图片预加载技术,当前显示的图片的上一张图片和下一张图片会先下载。
采用合理的数据处理算法
这种相对比较测试数据结构和算法的基础。
例如,将数组转换为多级结构的方法。
/**
*数组到树结构,时间复杂度O(n)
* @param列表数组
* @param idKey元素idKey
* @param parIdKey元素父id键
* @param parId第一级根节点的父Id值
* @return {[]}
*/
函数listToTree (list,idKey,parIdKey,parId) {
设map={ };
假设结果=[];
设len=list.length
//构建地图
for(设I=0;我leni ) {
//将数组中的数据变成键值对结构(这里数组和obj会互相引用,这是算法实现的重点)
map[list[I][idKey]]=list[I];
}
//构建一个树形数组
for(设I=0;我leni ) {
let item parid=list[I][parid key];
//顶级节点
if(itemParId===parId) {
result . push(list[I]);
继续;
}
//孤立节点,丢弃(其父节点不存在)
如果(!map[itemParId]){
继续;
}
//将当前节点插入到父节点的子节点中(因为是引用数据类型,如果obj中的节点发生变化,result中对应的节点也会相应变化)
if(映射[itemParId].儿童){
map[item parid]. children . push(list[I]);
}否则{
映射[itemParId]。children=[list[I]];
}
}
返回结果;
}
其他
除了以上方法,还有很多优化技术,但我在项目中并不经常使用。
冻结对象(以避免不必要的响应数据变得有响应)
长列表呈现-批量呈现
长列表渲染-动态渲染(vue-virtual-scroller)
.
首屏/体积优化
在我的项目中,首屏优化有以下几个优化方向。
卷
代码分段
网络
体积优化
压缩代码:webpack和vite的生产环境会默认压缩你的代码,一般不需要特殊处理。webpack也可以通过相应的压缩插件手动实现。
取消源映射:您可以检查您的打包产品中是否有. map文件。如果有,您可以将source-map的值设置为false或empty来关闭代码映射(这会占用很大的空间)。
启用gizp压缩:这需要开启服务器允许gizp传输,否则启用也没用(webpack有对应的gzip压缩插件,不同版本的webpack压缩插件可能不一样,建议先去官网查询)
代码分割
代码分段的作用是将封装好的产品分成小的产品,这些产品依赖于esModule。所以当你使用import()函数导入一个文件或者依赖项的时候,这个文件或者依赖项会被单独打包成一个小产品。惰性加载和异步组件都使用这个原则。
惰性路线加载
异步组件
对于UI库,我一般不采用按需加载组件的方式,而是更喜欢引入CDN的方式来优化。
网络
CDN:首先是上面提到的CDN介绍。在开发阶段使用本地库,通过配置打包的外部扩展消除了这些依赖性。然后通过CDN在html文件中介绍它们。
服务器:HTTP 2比较成熟;有了上述CDN的引入,我们可以利用HTTP2对网站的服务器推送功能,让浏览器提前加载这些CDN等文件。
打开gzip:这个上面已经提到了。原理是当客户端和服务器都支持gzip传输时,服务器会先发送gzip压缩的文件,然后客户端接收并解压。
打开缓存:一般情况下,我使用协商缓存,但这并不适用于所有情况。比如使用服务器推送的文件,不能随意修改文件名。所以我一般会固定主制作文件的文件名。
这就是这篇关于22个Vue优化技术(实际项目)的文章。更多相关的Vue优化技术,请搜索我们之前的文章或者继续浏览下面的相关文章。希望大家以后能多多支持我们!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。