v-if 和 v-for 的优先级
- v-for 优先于 v-if 被解析,从源码可知;
- 如果同时出现,每次渲染都会执行循环再判断条件,无论如何循环都不可避免,浪费性能;
- 要避免出现这种情况,常见处理方式是通过计算属性进行过滤。
data 为什么必须是个函数
vue 组件可能存在多个实例,如果使用对象形式定义 data, 会导致它们共用一个 data 对象,那么状态变更将会影响所有组件实例。采用函数形式定义,在initData 阶段会将其作为工厂函数返回全新 data 对象,有效规避多实例之间状态污染问题。
key 的作用
- key 的作用主要是为了高效的更新虚拟DOM,其原理是 vue 在 patch 过程中通过 key 可以精准判断两个节点是否是同一节点,从而避免频繁更新不同元素,使得整个 patch 的过程更加高效,减少 DOM 的操作,提高性能;
- 若不设置 key 的话可能还会带来一些隐藏的bug;
- vue 使用相同标签元素进行过渡切换时也会使用 key,其目的也是为了让 vue 可以区分它们,否则会替换其内部属性而不会触发过渡效果。
diff 算法
- diff 算法是虚拟 DOM 技术的核心:通过新旧虚拟 DOM 作对比,将变化的地方更新在真实 DOM 上;
- vue 中 diff 执行的时刻是组件实例执行其更新函数时,它会比对上一次渲染结果 oldVnode 和新的渲染结果 newVnode,此过程称为 patch;
- diff 过程整体遵循深度优先、同层比较的策略:两个节点之间比较会根据它们的是否拥有子节点或者文本节点做不同操作;比较两组节点是算法的重点,首先假设头尾节点可能相同做4次比对尝试,如果没有找到相同节点才按照通用方式遍历查找,查找结束再按情况处理剩下的节点;借助 key 可以非常精确找到相同节点,因此整个 patch 过程非常高效。
父子组件生命周期
- 创建:父 -> 子;
- 挂载:子 -> 父;
- 更新前: 父 -> 子;
- 更新后:子 -> 父;
- 销毁前: 父-> 子;
- 销毁后: 子-> 父。
vue 设计理念
-
易用性:vue 提供数据响应式、声明式模板语法和基于配置的组件系统等核心特性。这些特性使我们只需要关注应用的核心业务即可。
-
灵活性:渐进式框架的最大优点是灵活性,如果应用足够小,我们可能仅需要 vue 核心特性即可完成功能,随着应用规模不断扩大,我们才逐渐引入路由、状态管理、vue-cli 等库和工具,不管是应用体积还是学习难度都是一个逐渐增加的平和曲线。
-
高效性: 超快的虚拟的 DOM 和 diff 算法使得我们的应用拥有最佳的性能表现。vue3 中引入了 proxy 对数据响应式改进以及编译器中对于静态内容编译的改进都会让 vue 更加高效。
谈一谈 MVVM 和 MVC、MVP 的区别
-
这三者都是框架模式,它们设计的目标都是为了解决 model 和 view 的耦合问题。
-
MVC 模式出现在后端应用,如 Spring MVC、ASP.NET MVC 等,在前端领域的早期也有应用,如 Backbone.js。它们的优点是分层清晰,缺点是数据流混乱,灵活性较差带来的维护性问题。
-
MVP 模式在是 MVC 的进化形式,Presenter 作为中间层负责 MV 通信,解决了两者耦合问题,但 P 层过于臃肿会导致维护问题。
-
MVVM 模式在前端领域有广泛应用,它不仅解决 MV 耦合问题,还同时解决了维护两者映射关系的大量繁杂代码和 DOM 操作代码,在提高开发效率、可读性的同时还保持了优越的性能表现。
vue 性能优化方法
- 路由懒加载
const router = new VueRouter({
routes: [
{ path: '/foo', component: () => import('./Foo.vue') }
]
})
- keep-alive 缓存页面信息, 针对不同页面可以用 exclude 和 include 来控制
<template>
<div id="app">
<keep-alive>
<router-view/>
</keep-alive>
</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: function () {
return this.user.filter(function (user) {
return user.isActive
}
}
}
}
</script>
- 事件销毁 vue 组件销毁时,会自动解绑它的全部指令及事件监听器,但仅限于组件本身的事件。
created(){
this.timer = setInterval(this.refresh, 2000)
},
beforeDestroy(){
clearInterval(this.timer)
}
- 第三方库按需引入 像 element-ui 这样的第三方组件库可以按需引入避免打包后体积过大。
import Vue from 'vue';
import { Button, Select } from 'element-ui'
Vue.use(Button)
Vue.use(Select)
- Vue3.0 的新特性
- 1 更快:虚拟 DOM 重写,静态数和静态属性提升,基于 Proxy 的响应式系统。
- 2 更小: 通过摇树优化核心库体积。
- 3 更容易维护: TypeScript + 模块化。
- 4 更友好: 更容易和任何平台(Web、Android、IOS)一起使用,跨平台能力强。