当前位置: 首页 > Web前端 > vue.js

vue优化速查

时间:2023-04-01 01:33:45 vue.js

第一传送门:https://ssshooter.com/2021-03...拆分组件我也以为拆分子组件是为了抽象,但是实践告诉我拆分子组件是提高性能的一种方式(具体情况)。我在实际工作中遇到过这样的问题。有一个带有用于多个新条目的对话框的大表单。当数据较多时,填写新的数据会换卡。原因是,在一个组件中,修改一个值会引起整个组件的数据校验和diff。但是明知道大表上什么都没有改变,我又何必浪费时间去检查呢?为了解决这个问题,单独提取对话框是一种非常有效的优化方法。子组件更新时,默认不会触发父组件的更新,除非子组件改变了父组件的数据。我以elementUI的dialog为例:打开这个链接直接打开runnableexample写一个页面,里面包含两个dialog,一个直接写到页面,一个抽象成组件。下面是对话框组件的内容:从实践中可以看出,当对话框打开和关闭,输入框修改数据时,整个组件的渲染函数都会被触发,而无论dialog2是打开关闭还是进入,都不会触发父组件的更新。如果dialog所在组件的数据量小,差别不大,但当数据量大时,进入dialog时会有明显的滞后感。(一句话:对话框本身就是一个组件,内部更新不影响父组件)不仅如此,另一方面,父组件更新时,会渲染dialog1,不会渲染dialog2,这真是一箭双雕。(一句话:父组件更新时,没有数据变化的子组件没有变化。)即使不重用这个组件,也可以将对话框中使用的方法分离到一个单独的文件中,而不用将它们与方法混在一起的主页。如果一个对话框有很多逻辑,那么将它分离到一个单独的文件中绝对是一个好方法。但是当然也有缺点:一是数据交互有点不方便,不过总能用$parent和Vuex解决。第二个问题是“dialogData”道具的意外突变。(vue/no-mutating-props)修改dialogData.visible时会报错。作为Vue的最佳实践,父母给孩子的道具一定不能被孩子直接修改。我的观点是,如果您知道自己在做什么并且副作用不是太强……可能不会造成伤害,你们怎么看?如果你坚持最佳实践,有两个选项:emit、useon和emithonestly,还有几行代码:所以写等于:然后传递这个子组件中的.$emit('update:title',newTitle)更新父组件。$refs的可见性由dialog本身控制,而dialog的可见性是通过父组件中的refs设置的:this.$refs.child.visible=true反之亦然?也可以修改child中的parent(这不算修改prop,小技巧)this.$parent.visible=true关于更新粒度更详细的解释可以看这里:VueandReacthavedifferentupdategranularity对于组件有什么区别?PS:还有一个隐藏的结论。如果一个组件使用了一个插槽,子组件将与父组件一起重新渲染。Computed是官方文档强调的。可以说众所周知,computed可以缓存计算结果,依赖值不变的情况下减少计算时间。同样众所周知的是KeepAlive组件。减少重组件和插件的使用很多UI框架是完美的,但是因为太完美了,各种功能的交互可能会让你运行太慢或者调试不好。直接修改原来的框架当然是可以的,但是理解成本不低,而且修改之后,更新后合并代码就更难受了,所以还是宁愿自己做一个。我不想成为一个适用于全世界的轮子。因为每个人的需求不一样,如果想要做一个满足每个人要求的轮子,轮子会变得很重,我个人也不愿意看到……所以希望做一个“轮子轻”framework”,满足最低功能需求,让大家轻松修改,同时也不用担心持续更新越来越重。例如v-vld和[tbl]。(https://github.com/v-cpn/cpn-tbl)单向绑定甚至完全不绑定MDNObject.defineProperty()单向绑定是指数据使用defineProperty设置configurable为false,所以即data对应的defineReactive会跳过响应式设置:Object.defineProperty(data,key,{configurable:false,})但是仍然可以通过v-model给绑定目标赋值,只是界面不会任务完成后更新。这种方式适用于数据嵌套较深的情况,阻塞defineReactive后不会对数据中的子对象进行递归处理。(数据扁平化也可以避免递归。)完全不绑定就是官网写了Object.freeze一个对象,然后赋值。这样就不能直接改变对象的内部值(第一层),可以应用于纯显示的数据。缓存的ajax数据可以像普通的axiosget一样进行封装,直接替换原来的axios对象:env.VUE_APP_BASEURLletajax=axios.create({baseURL,withCredentials:true,})letajaxCache={}ajaxCache.get=(...params)=>{leturl=params[0]letoption=params[1]让id=baseURL+url+(option?JSON.stringify(option.params):'')if(sessionStorage[id]){returnPromise.resolve(JSON.parse(sessionStorage[id]))}returnajax.get(...params)}ajax.interceptors.response.use(function(response){//其他处理//...if(response.data.code==='20000'){letparams=response.config.paramsletid=response.config.url+(params?JSON.stringify(params):'')sessionStorage[id]=JSON.stringify(response.data.data)returnresponse.data.data}},function(错误){Message.error('Connectiontimeout')returnPromise.reject(error)})exportdefaultajaxCache功能组件

https://codesandbox.io/s/func...PS:因为函数式组件没有实例化,每次使用都会重新渲染。如果要完全静态,需要使用v-oncePS2:在Vue3中,函数式组件和普通组件的速度差异几乎可以忽略不计。减少这个的使用。简单的说就是需要关注computed、watch和render中this的每一个值的开销,其中包括依赖于collection的代码。其实这些代码只需要运行一次就够了{computed:{base(){return42},result({base,start}){letresult=startfor(leti=0;i<1000;i++){result+=Math.sqrt(Math.cos(Math.sin(base)))+base*base+base+base*2+base*3}returnresult},},}要了解有关此问题的更多信息,看这里:https://mp.weixin.qq.com/s/wu...v-show复用DOMv-show固然可以加速组件的显示,但是v-show和v-if之间的平衡应该也得到掌握。v-if可以用来优化首屏的加载速度。Sharding分批分配响应式数据,从而减少每次渲染的时间,提高用户感知的流畅度。重载组件可以使用v-if来延迟显示。requestAnimationFrame的相关传送门可以使用:requestAnimationFramePS:个人经验,如果多个ajax涉及同一堆数据,片段渲染的速度可能不会很快,我会选择使用Promise。allMergeRenderingSummary组件角度优化:拆分组件,使用组件级更新粒度优化更新速度谨慎使用重型组件,必要时自行构建,插件同样使用功能组件(低优先级)来处理响应式副作用:使用Responsiveanti-patternreduction使用这个来降低收集依赖时的渲染压力:v-show和v-ifbalance分片渲染Vue自带缓存:keepalivecomputed其他优化:数据缓存virtualscrollremovalconsole.log启用性能配置推荐文章揭示Vue.js九大性能优化技巧