1.列表使用唯一 key
v-for="item in activeList" :key="item.id"
原因是不使用 key
或者列表的 index
作为 key
的时候,每个元素对应的位置关系都是 index,直接导致我们插入的元素到后面的全部元素,对应的位置关系都发生了变更,所以在 patch 过程中会将它们全都执行更新操作,再重新渲染。这可不是我们想要的,我们希望的是渲染添加的那一个元素,其他四个元素不做任何变更,也就不要重新渲染。
2.使用 v-show 复用 DOM
<template><div><div v-show="status" class="on"><my-components /></div><section v-show="!status" class="off"><my-components ></section></div> </template>
v-show
:是渲染组件,然后改变组件的 display 为 block 或 none
v-if
:是渲染或不渲染组件
原理就是使用 v-if 当条件变化的时候,触发 diff 更新,发现新旧 vnode 不一致,就会移除整个旧的 vnode
,再重新创建新的 vnode
,然后创建新的 my-components
组件,又会经历组件自身初始化,render
,patch
等过程,而 v-show
在条件变化的时候,新旧 vnode
是一致的,就不会执行移除创建等一系列流程
所以对于可以频繁改变条件的场景,就使用 v-show 节省性能,特别是 DOM 结构越复杂收益越大
不过它也有劣势,就是 v-show 在一开始的时候,所有分支内部的组件都会渲染,对应的生命周期钩子函数都会执行,而 v-if 只会加载判断条件命中的组件,所以需要根据不同场景使用合适的指令
3. 变量本地化
原理:多次引用的变量保存起来,因为每次访问 this.xx
的时候,由于是响应式对象,所以每次都会触发 getter
,然后执行依赖收集的相关代码,如果使用变量次数越多,性能自然就越差
从需求上说在一个函数里一个变量执行一次依赖收集就够了,可是很多人习惯性的在项目中大量写 this.xx
,而忽略了 this.xx
背后做的事,就会导致性能问题了
var num = this.first; var sum = this.sumNum; for (let i = 0; i < 200; i++) {sum+= sum + num + i// 避免频繁引用 this.xx}
4. 第三方插件按需导入
import Vue from 'vue';
import { Button, Select } from 'element-ui';
import App from './App.vue';
Vue.component(Button.name, Button);
Vue.component(Select.name, Select); /* 或写为 *
Vue.use(Button) *
Vue.use(Select) */
new Vue({ el: '#app', render: h => h(App) });
5.路由懒加载
没有用路由懒加载
import Vue from 'vue'
import Router from 'vue-router'
const CPKB1 = () => import('@/views/centit/CPKB1')
const CK = () => import('@/views/centit/CK') //首页
export default new Router({
// mode: 'history', //打包的时候关闭
//saveScrollPostioin: true,
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else {
return {
x: 0,
y: 0
}
}
},
base:'/RAW/dist', //包名 一级目录和文件名一致 打包的时候打开
linkActiveClass: 'active',
routes: [
{
path:'/',
name:'CK',
component:CK,
mete:{title:'出库看板'},
children: [
{
path:'/CPKB1',
name:'CPKB1',
component:CPKB1,
mete:{title:'CPKB1'}
}
]
},
]
})
用了路由懒加载:
const router = new Router({routes: [{ path: '/CPKB', component: () => import('@/views/centit/CPKB1') },{ path: '/CK', component: require('@/views/centit/CK').default }] })
在进入这个路由的时候才会走对应的 component
,然后运行 import
编译加载组件,可以理解为 Promise
的 resolve
机制
import
:Es6语法规范、编译时调用、是解构过程、不支持变量函数等require
:AMD规范、运行时调用、是赋值过程,支持变量计算函数等
6. keep-alive缓存页面
<template><div id="app"><keep-alive include="['CPKB1','CPKB2']"><router-view></router-view></keep-alive></div> </template>
我们都可以通过内置组件 <keep-alive></keep-alive>
来把组件缓存起来,在组件切换的时候不进行卸载,这样当再次返回的时候,就能从缓存中快速渲染,而不是重新渲染,以节省性能
7. 事件的销毁
<script> export default {created() {this.timer = setInterval(this.load, 1000)addEventListener('touch', this.touch, false)},beforeDestroy() {clearInterval(this.timer)this.timer = nullremoveEventListener('touch', this.touch, false)} } </script>
Vue 组件销毁时,会自动解绑它的全部指令及事件监听器,但是仅限于组件本身的事件而对于定时器,addEventListener
注册的监听器等,就需要在组件销毁的生命周期钩子中手动销毁或解绑,以避免内存泄露.
8.项目图片懒加载
使用第三方图片懒加载库
9.长列表性能优化
针对只用于展示的数据,可以使用Object.freeze来处理。
原因如下:Vue 会通过 Object.defineProperty 对数据进行劫持,来实现视图响应数据的变化,然而有些时候我们的组件就是纯粹的数据展示,不会有任何改变,我们就不需要 Vue 来劫持我们的数据,在大量数据展示的情况下,这能够很明显的减少组件初始化的时间,那如何禁止 Vue 劫持我们的数据呢?可以通过 Object.freeze 方法来冻结一个对象,一旦被冻结的对象就再也不能被修改了。
export default {
data: () => ({
users: {}
}),
async created() {
const users = await axios.get("/api/users");
this.users = Object.freeze(users);
} };
10.vue 组件中的 data 是函数而不是对象
使用这种函数方式
export default {
name: 'app',
data() {
return {
level:''1"
};
},
}
不使用这种对象方式
export default {
name: 'app',
data: {
level:''1"
},
}
如果data 是一个纯碎的对象,则所有的实例将共享引用同一份 data 数据对象,无论在哪个组件实例中修改 data,都会影响到所有的组件实例。如果 data 是函数,每次创建一个新实例后,调用 data 函数,从而返回初始数据的一个全新副本数据对象。这样每复用一次组件,会返回一份新的 data 数据,类似于给每个组件实例创建一个私有的空间,让各个组件的实例各自独立,互不影响保持低耦合
11.不需要响应变化的数据可以放在实例里面,不要将所有的数据都放到 data 中
对应的lfl可以正常使用
created() {
this.lfl = '123'
},
data 中的数据都会增加 getter 和 setter,又会收集 watcher,这样还占内存。不需要响应式的数据我们可以定义在实例上。