vue代码写了那么多行了
你写废了吗
写废了吗
😭 🥱
computed
computed是计算属性,根据已有的变量做一些操作返回新的变量。
在面对computed,watch,method的情况下,能使用computed就尽量使用computed,因为computed具有缓存的功能。
举个例子🌰:
此时我们使用的就是method的方式,当点击按钮改变num的值,会触发重新渲染showFullName这个方法会被触发。
<div>
<div>{{showFullName()}}</div>
<div>{{num}}</div>
<button>click num + 1</button>
</div>
methods:{
showFullName(){
console.log('我是showFullName的方法')
return this.firstName + '-' + this.lastName
}
}
但是当我们讲method换成computed的时候,当点击按钮改变num的值, showFullName不会被触发,因为showFullName里面的变量的值没有改变,所以showFullName不再重新计算属性,使用的是之前缓存的值!
<div>
<div>{{showFullName}}</div>
<div>{{num}}</div>
<button>click num + 1</button>
</div>
computed:{
showFullName(){
console.log('我是showFullName的方法')
return this.firstName + '-' + this.lastName
}
}
v-for 与 v-if
v-for 与 v-if建议不要写在同一个dom元素/组件上,不是因为会报错,而是有点浪费性能。
<div v-for="item of list" v-if="showList">{{item.label}}</div>
当我们写上面那一行代码的时候,
😄期望:先判断v-if,如果为true,再v-for这个list
😂实际:v-for的优先级更高,会先执行v-for,为for循环上面的每个div添加v-if的判断,感觉有点笨笨的
<div v-if="showList">
<div v-for="item of list" >{{item.label}}</div>
</div>
所以,我们可以把v-if提到上一级元素上面,避免v-for 与 v-if写在同一个元素上。✌️
v-show 与 v-if
什么时候该使用v-show,什么时候该使用v-if,傻傻分不清🤔
v-if
: 第一次为true的时候,会创建组件,第一次为false的时候不会创建组件。切换v-if的值的时候会对组件进行卸载/重新创建。
v-show
:第一次无论是false还是true,都会创建组件,且不会随着v-show值的改变而卸载/重新创建。只是改变了css属性display:none,将其隐藏了起来。
总结如下:
如果是切换操作比较频繁的,建议使用v-show;
如果加载了之后只会出现一种结果,建议使用v-if,特别是为false的时候直接都不用创建组件;
v-for 循环上面加key
不建议使用index作为key值,虽然在纯展示的v-for里面是不会出现问题的,但是为了养成一个好习惯,我们可以每次都使用唯一值作为key的标示。
唯一值的key其实也是对dom的一个标示,因为唯一,所以精准。
<div v-for="item of list" :key="item.id">{{item.label}}</div>
那么为什么需要key是唯一值呢?
虚拟dom的diff比较,如果我们不添加一个唯一值key来标示这个dom,那么它们就会按照顺序来进行对比;如果添加了唯一值key来标示,自然会按照key来进行识别对比。
举个栗子🌰:
我们期望在ABCDE里面添加一个F,变成AB F CDE
但是因为我们没有给vdom标示唯一值,导致使用默认index的模式来进行比对
旧的树:A(1) B(2) C(3) D(4) E(5)
新的树: A(1) B(2) F(3) C(4) D(5) E(6)
比对一下,会发现C-F更新,D-C更新,E-D更新,E创建
总结:3个更新,一个创建
但是当我们使用了唯一值来标示vdom
旧的树:A(a) B(b) C(c) D(d) E(e)
新的树: A(a) B(b) F(f) C(c) D(d) E(e)
比对一下,只有F创建!
路由按需加载
当我们访问某一个路由的时候再加载回这个路由的资源,而不是在第一次进入页面的时候就把所以的页面资源全部加载回来。
提高了首屏加载的速度,提高了用户体验。
keep-alive
keep-alive 是 Vue 的内置组件,当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
beforeDestory
beforeDestory这个生命周期里面做一些销毁事件的监听或者定时器的操作
不然在组件销毁的时候,有些事件的监听是不会被销毁的,需要我们主动销毁
mounted(){
window.addEventListener('click', handleClick)
},
beforeDestory(){
window.removeEventListener('click', handleClick)
}
Object.freeze()
data(){
return {
info:{
name:'rose',
age:18
}
}
}
在vue初始化的时候,会遍历data里面的数据,给data里面的数据进行响应式设置getter,setter。作用是为了响应式数据的改变然后更新视图。
但是有的数据是永远不变的,用不上响应式,所以初始化设置getter,setter,就是性能的浪费。
所以可以加上Object.freeze()来表明,不做此数据的初始化。
data(){
return {
info:Object.freeze({
name:'rose',
age:18
})
}
}
组件拆分
组件拆分可以避免不必要的渲染,从而优化性能
当我们的组件的变量进行改变了之后,组件会进行重新渲染,但是很明显,有一些部分是没有必要渲染的,所以,我们可以通过把这部分的代码抽取成一个子组件来避免这些没有必要的渲染
举个简单的例子🌰:
<div>
<div>{{showFullName()}}</div>
<div>{{num}}</div>
<button>click num + 1</button>
</div>
methods:{
showFullName(){
console.log('我是showFullName的方法')
return this.firstName + '-' + this.lastName
}
}
当我们点击按钮进行num+1的时候,num值改变,导致页面重新渲染,结果 <div>{{showFullName()}}</div>
这一行代码也重新渲染了,导致showFullName
这个方法又执行了一次。
可能这一行代码没有什么感觉,但是想想如果这一行代码里面是1000行代码呢?
我们可以把这1000行代码拆成一个子组件
<div>
<Child/>
<div>{{num}}</div>
<button>click num + 1</button>
</div>
// -------Child----------
<div>{{showFullName()}}</div>
methods:{
showFullName(){
console.log('我是showFullName的方法')
return this.firstName + '-' + this.lastName
}
}
当我们点击按钮进行num+1的时候,num值改变,导致页面重新渲染,但是此时Child子页面的showFullName
方法不再执行!
总结一下就是:
合理子组件的拆分可以一定程度上避免无效的渲染,减少性能的浪费
总结
- 尽量使用computed进行缓存
- v-for 与 v-if不要写在同一个元素上面
- v-show 与 v-if的使用场景,频繁切换使用v-if反正v-show
- v-for 循环上面加唯一值key
- 实现路由按需加载
- 使用keep-alive缓存组件
- 在beforeDestory里面进行一些事件的销毁,取消事件的监听
- 不会改变的数据使用Object.freeze()进行包围
- 尝试组件拆分减少不必要的渲染
参考
最后
珍爱生命,多多运动