代码性能优化
减少Object.defineProperty的执行次数
* vue2使用他来订阅data中的所有属性
* vue3使用proxy,解决了如下问题
* vue2的defineProperty不能察觉属性的添加与删除
* vue2的defineProperty在数组的所有方法都是自己实现的
* proxy可以做到
* __只有需要在页面中响应式显示的属性,才放到data中__
只显示一次的变量处理
* 也可以用v-once
data(){
return {
// 应针对里面属性不修改
val:Object.freeze({a:1})
}
}
一次都不显示的变量处理
// 直接给this.挂载属性使用,如 this.timer
this.timer = setInterval();
keep-alive
* 避免频繁的创建与销毁组件
- `include` - 字符串或正则表达式。只有名称匹配的组件会被缓存。
- `exclude` - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
- `max` - 数字。最多可以缓存多少组件实例。
keep-alive实例
* 处理方案
<keep-alive :include="cacheComponents" max="20">
<router-view/>
</keep-alive>
<script>
import cacheComponents from 'config'; //组件名 ['01_defineProperty','02_freeze']
export default {
name:'main',
data(){
return {
cacheComponents
}
}
}
</script>
* max 会根据队列,后进后出,先取消缓存前面的
v-for和v-if为什么不能在一起
* 为什么要在一起?
* v-for执行权重较高
<div v-if="data">
{{ data.xxx }}
</div>
<!--业务需要-->
<div v-for="item in data" v-if="item.show">
</div>
<!--不好的示例:循环次数 * v-if的判断-->
<div v-for="item in data" v-if="data">
</div>
* v-for 第一层含义是判断元素是否存在
* v-for执行权重较高, 循环次数 * v-if的判断, 影响性能
* 跟for原理一致,会先判断被循环的元素是否存在,因此不用单独v-if判断元素
<!--不好的方式,n次判断v-if-->
<div v-for="u in users" :key="u.name" v-if="u.active">
{{ u.name }}
</div>
<!--中等方式,n次js判断-->
<div v-for="u in getActiveUser(users)" :key="u.name">
{{ u.name }}
</div>
<!--高等方式compunted,n次js判断,this.xxx相关属性原值不变,可以缓存-->
<div v-for="u in activeUsers" :key="u.name">
{{ u.name }}
</div>
* 总结:computed方式
* 1. 解决元素存在与否的判断
2. 执行元素次数的js判断
3. 原值相同,不会执行,走缓存
减少diff时不必要的DOM操作
* 索引作为key时,key会随着元素增加和移除而改变
* 在diff时,如果告诉了框架 老DOM中的张三 === 新DOM中的李四
* 就会造成不必要的DOM操作
* 尽可能给与准确的key作为diff对比的依据,否则会造成多余的操作(修改),
* vue会尽可能的就地复用元素,对比出差异,产生修改
减少渲染层级
减少DOM层级
* vue-fragment
import Fragment from 'vue-fragment'
Vue.use(Fragment.Plugin)
// or
import { Plugin } from 'vue-fragment'
Vue.use(Plugin)
// …
export const MyComponent {
template: '
<fragment>
<input type="text" v-model="message">
<span>{{ message }}</span>
</fragment>
',
data() { return { message: 'hello world }}
}
减少css层级
* 远离scoped
* 组件的style会将内容作为style标签,动态插入
* 大型项目 使用普通css,特定个例使用scoped css
* 对于template周期以外生成的结构,需要使用/deep/ 来查找
* 比如第三方的UI库的某些样式
* 比如v-html中的元素
分析消耗
* 1. 动态创建style标签 : 性能消耗
2. 浏览器解析多个style标签: DOM阻塞渲染
3. 给元素添加属性:性能消耗
4. 浏览器css选择器根据属性查找:阻塞css渲染
* 解决:尽可能少些scoped样式,而直接使用传统方式-全局
函数式组件
* 函数式: pure纯函数,只接收参数,返回数据,没有自身的状态
* function (n1,n2) { let xx = 1; return n1 + n2 }
* 默认组件有状态:自身数据data,生命周期(生命周期初始化)
* 没有生命周期 -> 没有初始化生命周期的js开销
<!--方式1:也可以使用模板的方式-->
<template functional>
<div>
<!-- 当前作用域就是context作用域`props` `children` `slots`:
`scopedSlots` `data``parent`:`listeners` -->
{{data.attrs.text}}
<slot></slot>
</div>
</template>
<!--方式2:-->
export default {
functional:true,
render(h,context){
return h('div',context.props.text,context.children)
}
}
参数列表
组件需要的一切都是通过 `context` 参数传递,它是一个包括如下字段的对象:
- `props`:提供所有 prop 的对象
- `children`:VNode 子节点的数组
- `slots`:一个函数,返回了包含所有插槽的对象
- `scopedSlots`:(2.6.0+) 一个暴露传入的作用域插槽的对象。也以函数形式暴露普通插槽。
- `data`:传递给组件的整个[数据对象](渲染函数 & JSX — Vue.js),作为 `createElement` 的第二个参数传入组件
- `parent`:对父组件的引用
- `listeners`:(2.3.0+) 一个包含了所有父组件为当前组件注册的事件监听器的对象。这是 `data.on` 的一个别名。
- `injections`:(2.3.0+) 如果使用了 [`inject`](API — Vue.js) 选项,则该对象包含了应当被注入的 property。
总结
1. data作为Vue框架中组件的运行基础,其底层Object.defineProperty承载了很重要的职责,尽可能减少不必要的该方法执行。
2. DOM层级目前受框架约定影响,可以尽可能借助第三方减少DOM的层级,优化渲染速度。
3. 尽量减少CSS选择器查找的效率,也可以提升渲染效率。
4. 计算属性是Vue中提供的一个响应式输出数据的方式, 内部已经实现缓存。
更多推荐
Vue代码优化
发布评论