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>