国色天香在线观看全集免费播放

你的位置:国色天香在线观看全集免费播放 > 男女扒开双腿猛进入免费看污 > 男女扒开双腿猛进入免费看污

十二个 Vue 开发中的性能优化小技巧

发布日期:2022-06-18 17:02    点击次数:122

十二个 Vue 开发中的性能优化小技巧

 性能优化,是每一个开发者都会遭逢的问题,极端是现时越来越兴趣体验,以及竞争越来越热烈的环境下,关于咱们开发者来说,只完成迭代,把功能做好是远远不够的,最迫切的是把居品做好,让更多人欣喜使用,让用户用得更爽,这不亦然咱们开发者价值与才调的体现吗。

兴趣性能问题,优化居品的体验,比起改几个无关痛痒的 bug 要有价值得多

本文记载了我在 Vue 技俩日常开发中的一些小技巧,妄语未几说,咱们出手吧

一. 长列表性能优化 1. 不做反馈式

比如会员列表、商品列表之类的,仅仅隧道的数据展示,不会有任何动态改换的场景下,就不需要对数据做反馈化处理,不错大大陶冶渲染速率

比如使用 Object.freeze() 冻结一个对象,MDN的描摹是 该门径冻结的对象不成被修改;即不成向这个对象添加新属性,不成删除已有属性,不成修改该对象已有属性的可胪列性、可树立性、可写性,以及不成修改已有属性的值,以及该对象的原型也不成被修改 

export default {   data: () => ({     userList: []  }),   async created() {     const users = await axios.get("/api/users");     this.userList = Object.freeze(users);  }  }; 

Vue2 的反馈式源码地址:src/core/observer/index.js - 144行 是这么的 

export function defineReactive (...){     const property = Object.getOwnPropertyDescriptor(obj, key)     if (property && property.configurable === false) {         return    }     ... } 

不错看到一出手就判断 configurable 为 false 的平直复返不做反馈式处理

configurable 为 false 默示这个属性是不成被修改的,而冻结的对象的 configurable 即是为 false

Vue3 里则是添加了反馈式flag,用于标识见识对象类型

2. 杜撰转动

如果是大数据很长的列表,一道渲染的话一次性创建太多 DOM 就会很是卡,这时就不错用杜撰转动,只渲染少部分(含可视区域)区域的施行,然后转动的时候,不休替换可视区域的施行,模拟出转动的效力 

<recycle-scroller   class="items"   :items="items"   :item-size="24"  >   <template v-slot="{ item }">     <FetchItemView       :item="item"       @vote="voteItem(item)"     />   </template>  </recycle-scroller> 

参考 vue-virtual-scroller、vue-virtual-scroll-list

旨趣是监听转动事件,动态更新需要傲气的 DOM,并意想出在视图中的位移,这也意味着在转动过程需要及时意想,有一定本钱,是以如果数据量不是很大的情况下,用闲居的转动就行

二. v-for 遍历幸免同期使用 v-if

为什么要幸免同期使用 v-for 和 v-if

在 Vue2 中 v-for 优先级更高,是以编译过程中会把列表元素一道遍历生成杜撰 DOM,再来通过 v-if 判断适合条目的才渲染,就会形成性能的挥霍,因为咱们但愿的是不适合条目的杜撰 DOM都不要生成

在 Vue3 中 v-if 的优先级更高,就意味着当判断条目是 v-for 遍历的列表中的属性的话,v-if 是拿不到的

是以在一些需要同期用到的场景,就不错通过意想属性来过滤一下列表,如下 

<template>     <ul>       <li v-for="item in activeList" :key="item.id">        {{ item.title }}       </li>     </ul>  </template>  <script>  // Vue2.x  export default {     computed: {       activeList() {         return this.list.filter( item => {           return item.isActive        })      }    }  }  // Vue3  import { computed } from "vue";  const activeList = computed(() => {   return list.filter( item => {     return item.isActive  })  })  </script
三. 列表使用惟一 key

比如有一个列表,咱们需要在中间插入一个元素,在不使用 key 有时使用 index 算作 key 会发生什么变化呢?先看个图

如图的 li1 和 li2 不会从头渲染,这个莫得争议的。而 li3、li4、li5 都会从头渲染

因为在不使用 key 有时列表的 index 算作 key 的时候,每个元素对应的位置关系都是 index,上图中的放荡平直导致咱们插入的元素到背面的一道元素,对应的位置关系都发生了变更,是以在 patch 过程中会将它们满盈推行更新操作,再从头渲染。

这可不是咱们想要的,咱们但愿的是渲染添加的那一个元素,其他四个元素不做任何变更,也就不要从头渲染

而在使用惟一 key  的情况下,每个元素对应的位置关系即是 key,来看一下使用惟一 key 值的情况下

这么如图中的 li3 和 li4 就不会从头渲染,因为元素施行没发生改换,对应的位置关系也莫得发生改换。

这亦然为什么 v-for 必须要写 key,而且不提议开发中使用数组的 index 算作 key 的原因

四. 使用 v-show 复用 DOM

v-show:是渲染组件,然后改换组件的 display 为 block 或 none  v-if:是渲染或不渲染组件

是以关于不错等闲改换条目的场景,就使用 v-show 节俭性能,极端是 DOM 结构越复杂收益越大

不外它也有症结, a级毛片免费观看在线播放即是 v-show 在一出手的时候,所有分支里面的组件都会渲染,对应的人命周期钩子函数都会推行,而 v-if 只会加载判断条目射中的组件,是以需要把柄不同场景使用合适的教导

比如底下的用 v-show 复用DOM,比 v-if/v-else 效力好 

<template>   <div>     <div v-show="status" class="on">       <my-components />     </div>     <section v-show="!status" class="off">       <my-components >     </section>  </div>  </template

旨趣即是使用 v-if 当条目变化的时候,触发 diff 更新,发现新旧 vnode 不一致,就会移除所有这个词旧的 vnode,再从头创建新的 vnode,然后创建新的 my-components 组件,又会阅历组件自身开动化,render,patch 等过程,而 v-show 在条目变化的时候,新旧 vnode 是一致的,就不会推行移除创建等一系列过程

五. 无气象的组件用函数式组件

关于一些纯展示,莫得反馈式数据,莫得气象料理,也无须人命周期钩子函数的组件,咱们就不错开辟成函数式组件,提高渲染性能,因为会把它当成一个函数来处理,是以支出很低

旨趣是在 patch 过程中关于函数式组件的 render 生成的杜撰 DOM,不会有递归子组件开动化的过程,是以渲染支出会低许多

它不错继承 props,但是由于不会创建实例,是以里面不成使用 this.xx 赢得组件属性,写法如下 

<template functional>   <div>     <div class="content">{{ value }}</div>   </div>  </template>  <script>  export default {   props: ['value']  }  </script>  // 有时  Vue.component('my-component', {   functional: true, // 默示该组件为函数式组件   props: { ... }, // 可选   // 第二个参数为陡立文,莫得 this   render: function (createElement, context) {     // ...  }  }) 
六. 子组件分割

先看个例子 

<template>   <div :style="{ opacity: number / 100 }">     <div>{{ someThing() }}</div>   </div>  </template>  <script>  export default {   props:['number'],男女扒开双腿猛进入免费看污   methods: {     someThing () { /* 耗时任务 */ }  }  }  </script

上头这么的代码中,每次父组件传过来的 number 发生变化时,每次都会从头渲染,而且从头推行 someThing 这个耗时任务

是以优化的话一个是宅心想属性,因为意想属性自身有缓存意想放荡的特质

第二个是拆分红子组件,因为 Vue 的更新是组件粒度的,固然第次数据变化都会导致父组件的从头渲染,但是子组件却不会从头渲染,因为它的里面莫得任何变化,耗时任务当然也就不会从头推行,因此性能更好,优化代码如下 

<template>  <div>     <my-child />  </div>  </template>  <script>  export default {  components: {     MyChild: {      methods: {         someThing () { /* 耗时任务 */ }       },        render (h) {        return h('div', this.someThing())     }    }  }  }  </script
七. 变量土产货化

浮浅说即是把会屡次援用的变量保存起来,因为每次走访 this.xx 的时候,由于是反馈式对象,是以每次都会触发 getter,然后推行依赖麇集的相干代码,如果使用变量次数越多,性能当然就越差

从需求上说在一个函数里一个变量推行一次依赖麇集就够了,然而许多人民俗性的在技俩中浩繁写 this.xx,而忽略了 this.xx 背后做的事,就会导致性能问题了

比如底下例子 

<template>    <div :style="{ opacity: number / 100 }"> {{ result  }}</div>  </template>  <script>  import { someThing } from '@/utils'  export default {   props: ['number'],  computed: {      base () { return 100 },      result () {       let base = this.base, number = this.number //   保存起来        for (let i = 0; i < 1000; i++) {        number += someThing(base) // 幸免等闲援用  this.xx       }        return number     }  }  }  </script
八. 第三方插件按需引入

比如 Element-UI 这么的第三方组件库不错按需引入幸免体积太大,极端是技俩不大的情况下,更莫得必要圆善引入组件库 

// main.js import Element3 from "plugins/element3";  Vue.use(Element3)  // element3.js  // 圆善引入  import element3 from "element3";  import "element3/lib/theme-chalk/index.css";   // 按需引入  // import "element3/lib/theme-chalk/button.css";  // ...  // import {   // ElButton,   // ElRow,   // ElCol,   // ElMain,   // .....  // } from "element3";  export default function (app) {   // 圆善引入   app.use(element3)    // 按需引入   // app.use(ElButton);  } 
九. 路由懒加载

咱们暴露 Vue 是单页应用,是以如果没灵验懒加载,就会导致干预首页时需要加载的施行过多,时期过长,就会出现长时期的白屏,很不利于用户体验,SEO 也不友好

是以不错去用懒加载将页面进行区别,需要的时候才加载对应的页面,以摊派首页的加载压力,减少首页加载时期

没灵验路由懒加载: 

import Home from '@/components/Home'  const router = new VueRouter({     routes: [      { path: '/home', component: Home }  ] }) 

用了路由懒加载: 

const router = new VueRouter({  routes: [    { path: '/home', component: () =>   import('@/components/Home') },    { path: '/login', component:   require('@/components/Home').default } ]  }) 

在干预这个路由的时候才会走对应的 component,然后运行 import 编译加载组件,不错贯穿为 Promise 的 resolve 机制

 import:Es6语法措施、编译时调用、是解构过程、不扶持变量函数等  require:AMD措施、运行时调用、是赋值过程,扶持变量意想函数等

更多关系前端模块化的施行不错看我另一篇著述 前端模块化措施详备追忆

十. keep-alive缓存页面

比如在表单输入页面干预下一步后,再复返上一步到表单页时要保留表单输入的施行、比如在列表页>笃定页>列表页,这么往复跳转的场景等

咱们都不错通过内置组件 <keep-alive></keep-alive> 来把组件缓存起来,在组件切换的时候不进行卸载,这么当再次复返的时候,就能从缓存中快速渲染,而不是从头渲染,以节俭性能

只需要包裹想要缓存的组件即可 

<template>   <div id="app">     <keep-alive>       <router-view/>     </keep-alive>  </div>  </template
 也不错用 include/exclude 来 缓存/不缓存 指定组件  可通过两个人命周期 activated/deactivated 来赢安妥前组件气象 十一. 事件的就义

Vue 组件就义时,会自动解绑它的一道教导及事件监听器,但是仅限于组件自身的事件

而关于定时器、addEventListener 注册的监听器等,就需要在组件就义的人命周期钩子中手动就义或解绑,以幸免内存透露 

<script>  export default {     created() {       this.timer = setInterval(this.refresh, 2000)      addEventListener('touchmove',   this.touchmove, false)    },     beforeDestroy() {       clearInterval(this.timer)        this.timer = null        removeEventListener('touchmove',  this.touchmove, false)    } }  </script
十二. 图片懒加载

图片懒加载即是关于有许多图片的页面,为了提高页面加载速率,只加载可视区域内的图片,可视区域外的比及转动到可视区域后再去加载

这个功能一些 UI 框架都有自带的,如果莫得呢?

推选一个第三方插件 vue-lazyload 

npm i vue-lazyload -S  // main.js  import VueLazyload from 'vue-lazyload'  Vue.use(VueLazyload)  // 接着就不错在页面中使用 v-lazy 懒加载图片了  <img v-lazy="/static/images/1.png"> 

有时我方造轮子,手动封装一个自界说教导,这里封装好了一个兼容各浏览器的版块的,主如果判断浏览器支不扶持 IntersectionObserver API,扶持就用它杀青懒加载,不扶持就用监听 scroll 事件+节流的时势杀青 

const LazyLoad = {   // install门径   install(Vue, options) {    const defaultSrc = options.default    Vue.directive('lazy', {      bind(el, binding) {        LazyLoad.init(el, binding.value, defaultSrc)    },       inserted(el) {       if (IntersectionObserver) {          LazyLoad.observe(el)     } else {          LazyLoad.listenerScroll(el)        }    },  }) },   // 开动化   init(el, val, def) {  el.setAttribute('data-src', val)     el.setAttribute('src', def)  },   // 欺诈IntersectionObserver监听el  observe(el) {     var io = new IntersectionObserver((entries) => {      const realSrc = el.dataset.src       if (entries[0].isIntersecting) {     if (realSrc) {         el.src = realSrc           el.removeAttribute('data-src')        }      }   })    io.observe(el)  },   // 监听scroll事件  listenerScroll(el) {     const handler =  LazyLoad.throttle(LazyLoad.load, 300)   LazyLoad.load(el)    window.addEventListener('scroll', () => {       handler(el)    })  },   // 加载信得过图片   load(el) {     const windowHeight =  document.documentElement.clientHeight   const elelTop = el.getBoundingClientRect().top     const elelBtm =   el.getBoundingClientRect().bottom    const realSrc = el.dataset.src     if (elTop - windowHeight < 0 && elBtm > 0) {    if (realSrc) {        el.src = realSrc         el.removeAttribute('data-src')      }    }  },   // 节流   throttle(fn, delay) {    let timer     let prevTime     return function (...args) {      const currTime = Date.now()     const context = this      if (!prevTime) prevTime = currTime      clearTimeout(timer)       if (currTime - prevTime > delay) {        prevTime = currTime           fn.apply(context, args)        clearTimeout(timer)         return      }     timer = setTimeout(function () {      prevTime = Date.now()      timer = null       fn.apply(context, args)    }, delay)   }  },  }  export default LazyLoad 

使用上是这么的,用 v-LazyLoad 代替 src 

<img v-LazyLoad="xxx.jpg" /> 
十三. SSR

这少量我在技俩中也莫得实践过,就不弄斧班门了