Vue 知识点
性能优化
- 编码优化
- 尽量减少 data 里的数据,data 的数据会增加 getter 和 setter,会收集对应的 watcher
- v-if 和 v-for 不能连用
- v-for 绑定事件时使用事件代理
- spa 采用 keep-alive 缓存组件
- 更多情况下,v-if 替代 v-show
- key 值保持唯一
- 路由懒加载、异步组件
- 防抖、节流
- 第三方模块按需导入
- 长滚动列表可视区域动态加载
- 图片懒加载
2 )体验优化
- 骨架屏
- pwa(渐进式 web 应用)
- (客户端,服务端)缓存优化、服务端开启 gzip 压缩
3 ) seo 优化
- 预渲染
- 服务端渲染 ssr
4)打包优化
- 压缩代码
- tree Shaking/Scope Hoisting
- cdn 加载第三方模块优化
- 多线程打包 happypack
- splitChunks 抽离公共文件
- sourceMap 优化
生命周期
1) Vue2 vs Vue3
| Vue2 | Vue3 |
|---|---|
| beforeCreate(组件创建之前) | setup(组件创建之前) |
| created(组件创建完成) | setup(组件创建完成) |
| beforeMount(组件挂载之前) | onBeforeMount(组件挂载之前) |
| mouted(组件挂载完成) | onMouted(组件挂载完成) |
| beforeUpdate(数据更新,虚拟 DOM 打补丁之前) | onBeforeUpdate(数据更新,虚拟 DOM 打补丁之前) |
| updated(数据更新,虚拟 DOM 渲染完成) | onUpdated(数据更新,虚拟 DOM 渲染完成) |
| beforeDestroy(组件销毁之前) | onBeforeDestroy(组件销毁之前) |
| destroyed(组件销毁之后) | onDestroyed(组件销毁之后) |
双向数据绑定
1) vue2
- 利用
Object.defineProperty()重新定义获取对象属性值get()和设置对象属性值set()来实现
2)vue3
- 使用原生 Proxy 替换
Object.defineProperty()
Proxy 优势
Object.defineProperty()无法监测数组下标变化,导致直接通过数组下标给数组设置值,不能实时响应。Object.defineProperty()只能劫持对象属性,要对每个对象属性遍历。Vue2.x 通过递归 + 遍历 data 对象实现数据监控,如果属性值也是对象就需要深度遍历,显然劫持整个对象才时更好的选择- Proxy 有以下优点
- 可以劫持整个对象
- 有 13 种劫持操作
避免 v-if 和 v-for 一起使用
- 因为 v-for 优先级高于 v-if,Vue3 相反。所以 2.x 中 v-for 会优先作用,造成性能浪费;3.x 中会导致 v-if 访问不了 v-for 中变量
组件设计原则
1 | (1)页面上每个独立的可视/可交互区域视为一个组件(比如页面的头部,尾部,可复用的区块) |
slot
- 作用: 让组件的可扩展性更强(能在组件内写其他内容)
- 渲染一个自定义组件的时候,向它“插入”一些内容。这个自定义组件会将起始标签和结束标签之间的内容渲染到自己模板中的“slot”组件所在的位置上
vue 核心
- 数据驱动和组件化思想
v-if 和 v-show 区别
- show 是显示和隐藏(display),if 是销毁和重建
常用修饰符
- 表单修饰符包括:lazy trim number
- 事件修饰符包括:stop prevent self once capture passive native
- 鼠标按钮修饰符包括:left right middle
on 可以监听多个方法
key 的作用
- 需要 key 给每个节点唯一标识,Diff 算法可以正确识别此节点,高效更新 DOM
$nextTick()
- 在下次更新 DOM 循环结束之后执行延迟回调。在修该数据之后立即调用获取更新后的 DOM
- $nextTick()主要使用了宏任务和微任务
- 放在$nextTick()执行的应该是会对 DOM 进行操作的 js 代码
子组件调用父组件方法
- 子组件调用
this.$parent.event() $emit()- 父组件方法传入子组件
父组件调用子组件方法
- 使用
$ref()
keep-alive
keep-alive 是 vue 内置组件,可以保留被包含的组件状态,避免重新渲染
触发视图更新方法
vue.set()vue.delete()- 数组对象直接修改属性
- splice 修改数组
- 数组整体修改
- Object. assign 或 lodash. assign
计算属性
定义: 当其依赖的属性的值发生变化时,计算属性会重新计算。反之则使用缓存中的属性值。计算属性是响应式的,必须依赖某一个数据实现。
computed 实现原理
我们知道 vue 的响应式基于发布订阅模式,依赖的收集追踪,一个属性被调用的函数,都放到订阅数组里,每依赖函数都是一个 Watcher,computed 中依赖该属性,那么 Dep 里就有一个惰性的 Watcher,为什么成为惰性的?是因为,在取值操作的时候会返回上一次计算结果。如果依赖值更新了,就会 notify 通知 Watcher 重新计算。
换种说法,computed 中的属性,通过代理,代理到 vue 的 data 上,data 上的属性都被依赖监听,当 computed 属性依赖的 data 改变时,会触发通知订阅者更新,于是 computed 的属性就重新计算了。
$route和$router 的区别
- $route 是路由信息对象,包括 path,params,hash,query,fullpath,matched,name 等路由信息参数
- $router 是路由实例对象,包含路由的跳转方法和钩子函数等
watch
- 主要用于监听数值变化,除了没有缓存和计算属性一样
什么情况下数据改变时不会触发视图更新
- v-for 遍历数组,当数组内容使用的是
arr[0].xx=xx更改数据 vue 无法监测到,vm.arr.length = newLength也是无法监测到的
vue 优点
- 低耦合
- 可重用性
- 独立开发
- 可测试
按需加载 webpack 设置
- require.ensure()
Vuex
- 属性
- State、 Getter、Mutation 、Action、 Module
vue-router 原理
- 通过对 URL 地址变化的监听,从而对不同组件进行渲染。URL 变化时渲染相应组件
MVVM
- MVVM 是 Model-View-ViewModel 的缩写。MVVM 是一种设计思想。Model 层代表数据模型,也可以在 Model 中定义数据修改和操作的业务逻辑;View 代表 UI 组件,它负责将数据模型转化成 UI 展现出来,ViewModel 是一个同步 View 和 Model 的对象(桥梁)。
- 在 MVVM 架构下,View 和 Model 之间并没有直接的联系,而是通过 ViewModel 进行交互,Model 和 ViewModel 之间的交互是双向的, 因此 View 数据的变化会同步到 Model 中,而 Model 数据的变化也会立即反应到 View 上。
- ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而 View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作 DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。
递归组件
- 组件可以在模版中调用自己,只能通过 name 实现
组件间通信
- 父子组件:props / $emit / $parent / ref / $attr
- 隔代组件:eventbus / vuex / provide + inject
- 兄弟组件:$parent / $root / eventbus / vuex
模版编译原理
- 生成 ast 树
- 优化
- codegen
computed 和 watch
- computed 是一个具备缓存的 watch
- watch 没有缓存
axios 请求同步化
- async await
组件在什么情况下会被销毁
- 页面关闭、路由跳转、v-if 和改变 key 值
访问根实例
- this.$root
vue2 给对象添加新属性
Vue.set()和vm.set()
检测数组变化
- vue2 通过重写数组方法,vue3 通过 Proxy 数据代理实现
路由守卫有哪些
- 全局守卫、路由独享守卫、组建内守卫
子组件不能改变父组件数据
- 所有 prop 都是单向下行绑定
- 父级 prop 更新会向下流到子组件。反过来会导致子组件意外改变父组件状态,从而导致数据流向难以理解
- 可以通过
$emit()通知父组件更新