分享更有价值
被信任是一种快乐

vue的性能优化方法有什么

文章页正文上

这期内容当中小编将会给大家带来有关vue的性能优化方法有什么,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。性能优化方法有:1、使用“v-slot:slotName”,而不是“slot=”slotName””;2、避免“v-for”和“v-if”同时使用;3、始终为“v-for”添加key,并且不要将index作为的key;4、使用延迟渲染等等。本教程操作环境:windows7系统、vue2.9.6版,DELL G3电脑。我们在使用 Vue 或其他框架的日常开发中,或多或少的都会遇到一些性能问题,尽管 Vue 内部已经帮助我们做了许多优化,但是还是有些问题是需要我们主动去避免的。我在我的日常开中,以及网上各种大佬的文章中总结了一些容易产生性能问题的场景以及针对这些问题优化的技巧,这篇文章就来探讨下,希望对你有所帮助。v-slot是 2.6 新增的语法,具体可查看:Vue2.6,2.6 发布已经是快两年前的事情了,但是现在仍然有不少人仍然在使用slot="slotName"这个语法。虽然这两个语法都能达到相同的效果,但是内部的逻辑确实不一样的,下面来看下这两种方式有什么不同之处。我们先来看下这两种语法分别会被编译成什么:使用新的写法,对于父组件中的以下模板:会被编译成:使用旧的写法,对于以下模板:会被编译成:通过编译后的代码可以发现,旧的写法是将插槽内容作为 children 渲染的,会在父组件的渲染函数中创建,插槽内容的依赖会被父组件收集(name 的 dep 收集到父组件的渲染 watcher),而新的写法将插槽内容放在了 scopedSlots 中,会在子组件的渲染函数中调用,插槽内容的依赖会被子组件收集(name 的 dep 收集到子组件的渲染 watcher),最终导致的结果就是:当我们修改 name 这个属性时,旧的写法是调用父组件的更新(调用父组件的渲染 watcher),然后在父组件更新过程中调用子组件更新(prePatch => updateChildComponent),而新的写法则是直接调用子组件的更新(调用子组件的渲染 watcher)。这样一来,旧的写法在更新时就多了一个父组件更新的过程,而新的写法由于直接更新子组件,就会更加高效,性能更好,所以推荐始终使用v-slot:slotName语法。这一点已经被提及很多次了,计算属性最大的一个特点就是它是可以被缓存的,这个缓存指的是只要它的依赖的不发生改变,它就不会被重新求值,再次访问时会直接拿到缓存的值,在做一些复杂的计算时,可以极大提升性能。可以看以下代码:这个例子中,在 created、mounted 以及模板中都访问了 superCount 属性,这三次访问中,实际上只有第一次即created时才会对 superCount 求值,由于 count 属性并未改变,其余两次都是直接返回缓存的 value。对于某些组件,如果我们只是用来显示一些数据,不需要管理状态,监听数据等,那么就可以用函数式组件。函数式组件是无状态的,无实例的,在初始化时不需要初始化状态,不需要创建实例,也不需要去处理生命周期等,相比有状态组件,会更加轻量,同时性能也更好。具体的函数式组件使用方式可参考官方文档:函数式组件我们可以写一个简单的 demo 来验证下这个优化:UserProfile免费云主机、域名 这个组件只渲染了 props 的 name,然后在 App.vue 中调用 500 次,统计从 beforeMount 到 mounted 的耗时,即为 500 个子组件(UserProfile)初始化的耗时。经过我多次尝试后,发现耗时一直在 30ms 左右,那么现在我们再把改成 UserProfile 改成函数式组件:此时再经过多次尝试后,初始化的耗时一直在 10-15ms,这些足以说明函数式组件比有状态组件有着更好的性能。以下是两个使用 v-show 和 v-if 的模板这两者的作用都是用来控制某些组件或 DOM 的显示 / 隐藏,在讨论它们的性能差异之前,先来分析下这两者有何不同。其中,v-if 的模板会被编译成:可以看到,v-if 的部分被转换成了一个三元表达式,visible 为 true 时,创建一个 UserProfile 的 vnode,否则创建一个空 vnode,在 patch 的时候,新旧节点不一样,就会移除旧的节点或创建新的节点,这样的话UserProfile也会跟着创建 / 销毁。如果UserProfile组件里有很多 DOM,或者要执行很多初始化 / 销毁逻辑,那么随着 visible 的切换,势必会浪费掉很多性能。这个时候就可以用 v-show 进行优化,我们来看下 v-show 编译后的代码:v-show被编译成了directives,实际上,v-show 是一个 Vue 内部的指令,在这个指令的代码中,主要执行了以下逻辑:它其实是通过切换元素的 display 属性来控制的,和 v-if 相比,不需要在 patch 阶段创建 / 移除节点,只是根据v-show上绑定的值来控制 DOM 元素的style.display属性,在频繁切换的场景下就可以节省很多性能。但是并不是说v-show可以在任何情况下都替换v-if,如果初始值是false时,v-if并不会创建隐藏的节点,但是v-show会创建,并通过设置style.display='none'来隐藏,虽然外表看上去这个 DOM 都是被隐藏的,但是v-show已经完整的走了一遍创建的流程,造成了性能的浪费。所以,v-if的优势体现在初始化时,v-show体现在更新时,当然并不是要求你绝对按照这个方式来,比如某些组件初始化时会请求数据,而你想先隐藏组件,然后在显示时能立刻看到数据,这时候就可以用v-show,又或者你想每次显示这个组件时都是最新的数据,那么你就可以用v-if,所以我们要结合具体业务场景去选一个合适的方式。在动态组件的场景下:这个时候有多个组件来回切换,currentComponent每变一次,相关的组件就会销毁 / 创建一次,如果这些组件比较复杂的话,就会造成一定的性能压力,其实我们可以使用 keep-alive 将这些组件缓存起来:keep-alive的作用就是将它包裹的组件在第一次渲染后就缓存起来,下次需要时就直接从缓存里面取,避免了不必要的性能浪费,在讨论上个问题时,说的是v-show初始时性能压力大,因为它要创建所有的组件,其实可以用keep-alive优化下:这样的话,初始化时不会渲染UserProfileB组件,当切换visible时,才会渲染UserProfileB组件,同时被keep-alive缓存下来,频繁切换时,由于是直接从缓存中取,所以会节省很多性能,所以这种方式在初始化和更新时都有较好的性能。但是keep-alive并不是没有缺点,组件被缓存时会占用内存,属于空间和时间上的取舍,在实际开发中要根据场景选择合适的方式。这一点是 Vue 官方的风格指南中明确指出的一点:Vue 风格指南如以下模板:会被编译成:可以看到,这里是先遍历(v-for),再判断(v-if),这里有个问题就是:如果你有一万条数据,其中只有 100 条是isActive状态的,你只希望显示这 100 条,但是实际在渲染时,每一次渲染,这一万条数据都会被遍历一遍。比如你在这个组件内的其他地方改变了某个响应式数据时,会触发重新渲染,调用渲染函数,调用渲染函数时,就会执行到上面的代码,从而将这一万条数据遍历一遍,即使你的users没有发生任何改变。为了避免这个问题,在此场景下你可以用计算属性代替:这样只会在users发生改变时才会执行这段遍历的逻辑,和之前相比,避免了不必要的性能浪费。这一点是 Vue 风格指南中明确指出的一点,同时也是面试时常问的一点,很多人都习惯的将 index 作为 key,这样其实是不太好的,index 作为 key 时,将会让 diff 算法产生错误的判断,从而带来一些性能问题,你可以看下 ssh 大佬的文章,深入分析下,为什么 Vue 中不要用 index 作为 key。在这里我也通过一个例子来简单说明下当 index 作为 key 时是如何影响性能的。看下这个例子:这里有一个 list,会渲染出来a b,点击后会执行reverse方法将这个 list 颠倒下顺序,你可以将这个例子复制下来,在自己的电脑上看下效果。我们先来分析用id作为 key 时,点击时会发生什么,由于 list 发生了改变,会触发Parent组件的重新渲染,拿到新的vnode,和旧的vnode去执行patch,我们主要关心的就是patch过程中的updateChildren逻辑,updateChildren就是对新旧两个children执行diff算法,使尽可能地对节点进行复用,对于我们这个例子而言,此时旧的children是:执行reverse后的新的children是:此时执行updateChildrenupdateChildren会对新旧两组 children 节点的循环进行对比:通过sameVnode判断两个节点是相同节点的话,就会执行相应的逻辑:sameVnode主要就是通过 key 去判断,由于我们颠倒了 list 的顺序,所以第一轮对比中:sameVnode(oldStartVnode, newEndVnode)成立,即旧的首节点和新的尾节点是同一个节点,此时会执行patchVnode逻辑,patchVnode中会执行prePatchprePatch中会更新 props,此时我们的两个节点的propsData是相同的,都为{color: '#0f0',message: '绿色'},这样的话Item组件的 props 就不会更新,Item也不会重新渲染。再回到updateChildren中,会继续执行"移动oldStartVnode节点"的操作,将 DOM 元素。移动到正确位置,其他节点对比也是同样的流程。可以发现,在整个流程中,只是移动了节点,并没

相关推荐: DIV+CSS开发浏览器的兼容性问题有哪些

这篇文章主要介绍“DIV+CSS开发浏览器的兼容性问题有哪些”,在日常操作中,相信很多人在DIV+CSS开发浏览器的兼容性问题有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”DIV+CSS开发浏览器的兼容性问题有哪些”的疑惑…

文章页内容下
赞(0) 打赏
版权声明:本站采用知识共享、学习交流,不允许用于商业用途;文章由发布者自行承担一切责任,与本站无关。
文章页正文下
文章页评论上

云服务器、web空间可免费试用

宝塔面板主机、支持php,mysql等,SSL部署;安全高速企业专供99.999%稳定,另有高防主机、不限制内容等类型,具体可咨询QQ:360163164,Tel同微信:18905205712

主机选购导航云服务器试用

登录

找回密码

注册