vue项目的性能优化

509 阅读2分钟

vue性能优化

一.路由懒加载

1.为什么要使用路由懒加载:加快首屏加载时间

2.实现代码

// 未使用懒加载写法
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'

Vue.use(Router)

export default new Router({
    routes: [
    {
        path: '/',
        name: 'HelloWorld',
        component:HelloWorld
    }
    ]
})
// vue异步组件实现懒加载
import Vue from 'vue'
import Router from 'vue-router'
// 此处省去之前导入的HelloWorld模块
Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: resolve=>(require(["@/components/HelloWorld"],resolve))
    }
  ]
})
// 最佳实践
// ES 提出的import方法
import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)
export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: ()=>import("@/components/HelloWorld")
    }
  ]
})

二.keep-alive 缓存页面

1.keep-alive可以干嘛:对组件进行缓存,达到节省性能的目的

2.实现代码

<!-- 利用include、exclude属性 -->
<keep-alive include="bookLists,bookLists">
      <router-view></router-view>
</keep-alive>
<keep-alive exclude="indexLists">
      <router-view></router-view>
</keep-alive>
<!-- include属性表示只有name属性为bookLists,bookLists的组件会被缓存,(注意是组件的名字,不是路由的名字)其它组件不会被缓存exclude属性表示除了name属性为indexLists的组件不会被缓存,其它组件都会被缓存 -->
// 利用meta属性
export default[
 {
  path:'/',
  name:'home',
  components:Home,
  meta:{
    keepAlive:true //需要被缓存的组件
 },
 {
  path:'/book',
  name:'book',
  components:Book,
  meta:{
     keepAlive:false //不需要被缓存的组件
 } 
]
<keep-alive>
  <router-view v-if="this.$route.meat.keepAlive"></router-view>
<!--这里是会被缓存的组件-->
</keep-alive>
<keep-alive v-if="!this.$router.meta.keepAlive"></keep-alive>
<!--这里是不会被缓存的组件-->

三.使用v-show复用DOM

<template> 
  <div class="cell">
    <!--这种情况用v-show复用DOM,比v-if效果好-->     
    <div v-show="value" class="on">
      <Heavy :n="10000"/>
    <!--消耗性能的组件Heavy-->     
    </div>
    <section v-show="!value" class="off">
      <Heavy :n="10000"/>
    </section>
  </div>
</template>

四.v-for遍历避免同时使用v-if

<template>
    <ul>
      <li
        v-for="user in activeUsers"
        :key="user.id">
        {{ user.name }}
      </li>
    </ul>
</template>
<script>
    export default {
        computed: {
          activeUsers: () => {
            return this.users.filter(user => user.isActive )
          }
        }
    }
</script>

五.长列表性能优化

a:如果列表是纯粹的数据展示,不会有任何改变,就不需要做响应化

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

b.如果是大数据长列表,可采用虚拟滚动,只渲染少部分区域的内容

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

参考github.com/Akryum/vue-… 参考github.com/tangbc/vue-…

六.事件的销毁

Vue 组件销毁时,会自动解绑它的全部指令及事件监听器,但是仅限于组件本身的事件。

created () {
    this.timer = setInterval(this.refresh, 2000)
},
beforeDestory () {
    clearInterval(this.timer)
}

七.图片懒加载

对于图片过多的页面,为了加速页面加载速度,所以很多时候我们需要将页面内未出现在可视区域 内的图片先不做加载, 等到滚动到可视区域后再去加载。

<img v-lazy="/static/img/1.png">

八.第三方插件按需引入

像element-ui这样的第三方组件库可以按需引入避免体积太大。

import Vue from 'vue'
import { Button, Select } from 'element-ui'
Vue.use(Button)
Vue.use(Select)

九.无状态的组件标记为函数式组件

<template functional>
    <div class="cell">
        <div v-if="props.value" class="on"></div>
        <section v-else class="off"></section>
    </div>
</template>
<script>
export default {
    props: ['value']
}
</script>

十.子组件分割

一个组件一个wactcher,如果一个页面大部分是静态的,只有小部分的动态的,把动态部分单独分割成组件

<template>
    <div>
        <ChildComp/>
    </div>
</template>
<script>
export default {
    components: {
        ChildComp: {
            methods: {
                heavy () { /* 耗时任务 */ }
            },
            render (h) {
                return h('div', this.heavy())
            }
        }
    }
}
</script>

十一.变量本地化

<template>
    <div :style="{ opacity:start / 300 }">
        {{ result }}
    </div>
</template>
<script>
import { heavy } from '@/utils'

export default {
    props: ['start'],
    computed: {
        base () { return 42 },
        result () {
            const base = this.base // 不要频繁引用this.base
            let result = this.start
            for (let i = 0; i < 1000; i++) {
                result += heavy(base)
            }
            return result
        }
    }
}
</script>