谈谈对 MVVM 的理解
MVVM 是 Model-View-ViewModel 的锁鞋,也就是把 MVC 中的 Controller 演变成 ViewModel。Model 代表数据模型,View 代表 UI 组件,ViewModel 是 VIew 和 Model 的桥梁,数据会绑定到 ViewModel 上,并自动将数据渲染到页面中,视图变化的时候会通知 ViewModel 更新数据。
Vue3 对比 Vue2 有哪些优势
性能更好,打包体积更小,更好的 ts 支持,更好的代码组织,更好的逻辑抽离,更多的新功能
Vue3 的新特性
- 性能提升
- 响应式性能提升,由原来的
Object.defineProperty
改为ES6
的 Proxy,速度更快 - 重写了
Vdom
,diff 算法优化,增加了静态标记 - 进行了模板编译优化,静态提升,不参与更新的元素只被创建一次
- 更高效的组件初始化
- 响应式性能提升,由原来的
- 更好的支持 TypeScript
- Vue2 选用 Flow 做类型检查来避免一些因类型问题导致的错误,但是 Flow 对于一些复杂场景类型的检查,支持得并不好
- Vue3 抛弃了 Flow,使用 TypeScript 重构了整个项目
- TypeScript 提供了更好的类型检查,能支持复杂的类型推断
- 新增 Composition API
- 提高代码逻辑的复用性和维护性,同时代码压缩性更强
- 定义 methods、watch、computed、data 都放在了 setup() 函数中
- setup() 函数会在 created() 之前执行,beforeCreate > setup > cteated
- 新增组件
- Fragment 不再限制 template 只有一个根节点
- Teleport 传送门,允许我们将控制的内容传送到任意 DOM中,就是指定组件挂载位置,如通过 #id
- Suspense 等待异步组件时渲染一些额外的内容,让应用有更好的用户体验
- Tree-shaking,支持摇树优化
会将不需要的模块修剪掉,打包真正需要的模块,优化后的项目体积只有原来的一般,加载速度会更快。 - Custom Renderer API,自定义渲染器
实现 DOM 的方式进行 WebGL 编程
Vue3 和 Vue2 的区别
- 源码组织方式变化,使用 TypeScript 重写
- 支持 Compsition API,基于函数的 API,更加灵活地组织组件逻辑(Vue2 是 Options API)
- 响应式系统提升,从 defineProperty 到 Proxy,可监听动态新增删除属性以及数组的变化
- 编译优化,Vue2 通过标记静态根节点优化 diff,Vue3 标记和提升所有静态根节点,diff 的时候只需要对比动态节点内容
- 打包体积优化,移除了不常用的 API(inline-template、filter)
- 生命周期的变化,使用 setup 代替了之前的 beforeCreate 和 created
- Vue3 的 template 模板支持多个根标签
- 更多
Vue3 性能提升主要是通过哪些方面体现的
- 编译阶段优化
回顾 Vue2,我们知道每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把用到的数据 property 记录为依赖,当依赖发生变化,触发 setter,则会通知 watcher,从而使关联的组件重新渲染,因此,Vue3 在编译阶段做了进一步的优化:- diff 算法优化
增加了静态标记,其作用是为了在发生变化的地方添加一个 flag 标记,下次发生变化时直接在该处进行比较。 - 静态提升
Vue3 对不参与更新的元素,会做静态提升,只会被创建一次,在渲染时直接服用。避免了重复的创建操作,优化内存。 - 事件监听缓存
默认情况下绑定事件行为会被视为动态绑定(未开启事件监听器缓存),所以每次都会追踪它的变化,开启事件侦听器缓存后,没有了静态标记,下次 diff 算法的时候直接使用。 - SSR 优化
当静态内容大到一定量级的时候,会用 createStaticVNode 方法在客户端生成一个 static node,这些静态 node会被直接 innerHTML,就不需要创建对象,然后根据对象渲染
- diff 算法优化
- 源码体积
相比 Vue2,Vue3 整体体积变小了,移除了一些不常用的 API,最重要的是增加了 Treeshaking,任何一个函数,如 ref、reactive、computed 等,仅仅在用到的时候才打包,没用到的模块会被移除,减小体积。 - 响应式系统
Vue2 采用 defineProperty 来实现数据劫持,然后进行深度遍历所有属性,给每个属性添加 getter 和 setter 实现响应式。
Vue3 采用 Proxy 重写了响应式系统,因为 proxy 可以对整个对象进行监听,不需要深度遍历,另外还解决了 2 中的不足:- 可以监听动态属性的添加
- 可以监听数组的索引和数组的 length 属性
- 可以监听删除属性
Vue3 的响应式原理
Proxy只会代理对象的第一层,那么Vue3又是怎样处理这个问题的呢?
判断当前Reflect.get的返回值是否为Object,如果是则再通过reactive方法做代理, 这样就实现了深度观测。
监测数组的时候可能触发多次get/set,那么如何防止触发多次呢?
我们可以判断key是否为当前被代理对象target自身属性,也可以判断旧值与新值是否相等,只有满足以上两个条件之一时,才有可能执行trigger。
v-model 双向绑定的原理是什么
v-model 本质上是一个语法糖,可以看成是 value + input 方法的组合。可以通过 model 属性的 prop 和 event 属性来进行自定义。原生的 v-model 会根据标签的不同生成不同的事件和属性。
Options API 的生命周期
- beforeCreate
- created
- beforeMount
- onMounted
- beforeUpdate
- onUpdated
- beforeUnmount
- onUnmounted
- onActivated
- onDeactivated
- onErrorCaptured
Composition API 和 Options API
Options API 是一种基于对象的 API,用组件的选项(data、computed、methods、watch)组织逻辑在大多数情况下是可行的,然后当组件变得复杂,导致对应属性的列表也会增加,可能会导致组件难以理解和阅读。
Composition API 是一种函数式的 API,组件根据逻辑功能来组织,一个功能定义的所有 API 会放在一起(更加的 高内聚、低耦合)
Composition API 相对于 Options API 有以下优点:
- 逻辑组织
- Options API 在处理大型组件时,内部逻辑点容易碎片化,可能同时存在于各选项中(data、computed、methods、watch),我们必须不断地“跳转”相关代码的选项块,这种碎片化使得理解和维护复杂组件变得困难。
- Composition API 把某个逻辑相关代码全部放在一个函数里。
- 逻辑复用
在 Vue2 中,使用混入函数 mixin 会存在两个非常明显的问题,命名冲突和数据来源不清晰,而 Composition API 可以通过编写多个 hooks 函数来实现逻辑复用。
reactive、ref 、toRef 和 toRefs
- ref,函数可以接受基本数据类型和引用数据类型,创建的响应式数据在模板中可以直接使用,在 JavaScript 中使用需要通过 .value 的形式。
- reactive,函数只能接受引用数据类型。
- toRef,函数可以把响应式对象中的某个属性转换成 ref 对象。
- toRefs,将一个响应式对象转为普通对象,对象的每一个属性都转换成 ref 对象。
script setup
Vue3 的语法糖,简化了组合式 API 的写法
- 属性和方法无需返回,可直接使用
- 引入的组件会自动注册,无需通过 components 手动注册
- 使用 defineProps 接收父组件传递的值
- useAttrs 获取属性,useSlots 获取插槽,defineEmits 获取自定义事件
- 默认不会对外暴露任何属性,如果有需要可使用 definExpose
在 setup 中如何获取组件实例
使用 getCurrentInstance() 方法来获取组件实例,该方法返回一个对象,对象包含了组件实例及其相关信息。
1 | import { getCurrentInstance } from 'vue' |
v-if 和 v-for 的优先级
在 Vue2 中 v-for 优先级更高,但在 Vue3 中 v-if 优先级更高。
watch 和 watchEffect
watch 和 watchEffect 都是监听器,watchEffect 是一个副作用函数,它们之间的区别:
- watch 需要指定监视的数据源和回调函数,watchEffect,不需要指定监视的数据源,它会自动追踪响应式数据的变化,回调函数中用到了哪个数据,就监视哪个数据
- watch 可以访问到旧值和新值,watchEffect 只能访问到新值
- watch 运行的时候不会立即执行,值改变后才会执行,而 watchEffect 会立即执行一次,这一点通过 watch 的配置项 immediate 可以改变
- watchEffect 有点像 computed
- 但 computed 注重的计算出来的值(回调函数的返回值),所以必须要写返回值
- 而 watchEffect 注重的是过程(回调函数的执行),所以不用写返回值
- watch 与 Vue2 中的 watch 配置功能一致,但需要注意
- 监视 reactive 定义的响应式数据时,oldValue 无法正确获取,且会强制开启深度检测(deep 配置失效)
- 监视 reactive 定义的响应式数据中某个属性时,deep 配置有效
Vue2/Vue3 组件通信方式
Vue3 通信方式
- props
- $emit
- expose/ref
- $attrs
- v-model
- provide/inject
- Vuex/pinia
- mitt
Vue2 通信方式
- props
- $emit/v-on
- .sync
- v-model
- ref
- children/parent
- attrs/listeners
- provide/inject
- eventBus
- Vuex
- $root
- slot
- Vue 的生命周期有哪些,以及每个生命周期做了什么
- Vue 的响应式原理是什么,Vue3 中是如何实现的
- Vue3 和 Vue2 有什么区别
- 谈谈对 MVVM 的理解
- 在 Vue2 中如何检测数据的变化
- v-model 双向绑定的原理是什么
- Vue2 和 Vue3 渲染器的 diff 算法分别说一下
- Vue2/3 组件通信方式
- Vue 的路由实现,hash 和 history 路由实现原理
- 说一下 v-if 和 v-show 的区别
- keep-alive 的常用属性和实现原理
- nextTick 的作用是什么,实现原理是什么
- 说一下 Vue SSR 的实现原理
- Vue 组件的 data 为什么必须是函数
- 说一下 Vue 的 computed 的实现原理
- 说一下 Vue complier 的实现原理
- Vue 和 React 的区别
- 说一下 watch 与 computed 的区别是什么,以及对应的使用场景
- Vue 有哪些修饰符
- 如何实现 Vue 项目的性能优化
- Vue 中的 SPA 应用如何优化首屏加载速度
- Vue 中的 key 的作用是什么
- 你的接口请求一般放在哪个生命周期中?为什么
- Vue3 对比 Vue2 有什么优势
- 描述 Vue3 的生命周期
- 如何看待 Composition API 和 Options API
- Vue3 有什么更新
- Proxy 和 Object.defineProperty 的区别
- Vue3 升级了哪些重要功能
- Vue2 和 Vue3 核心 diff 算法区别
- Vue3 为什么比 Vue2 快
- Vue3 如何实现响应式
- Vue3 编译做了哪些优化
- watch 和 watchEffect 的区别
- 请介绍 Vue3 中的 Teleport(瞬移) 组件,是什么以及使用场景
- 如何理解 reactive、ref、toRef 和 toRefs
- 谈谈 pinia
- EventBus 和 mitt 的区别
- script setup 是什么
- v-if 和 v-for 的优先级
- setup 中如何获取组件实例
- Vue3 中的 Suspense 是什么,如何是用它来处理异步组件
- Vue3 性能提升主要是通过什么方面体现的
- Vue3 为什么要用 Proxy API 替代 defineProperty API
- Vue3 中的 Treeshaking 特性
- 说说你对 SPA 单页面的理解,它的优缺点分别是什么
- v-show 与 v-if 有什么区别
- Class 与 Style 如何动态绑定
- 怎么理解 Vue 的单向数据流
- computed 和 watch 的区别和运用的场景
- 直接给一个数组项赋值,Vue 能检测到变化吗
- 谈谈你对 Vue 生命周期的理解
- Vue 的父组件和子组件生命周期钩子函数执行顺序
- 在哪个生命周期内调用异步请求
- 在什么阶段才能访问操作DOM
- 父组件可以监听到子组件的生命周期吗
- 谈谈你对 keep-alive 的了解
- 组件中 data 为什么是一个函数
- v-model 的原理
- Vue 组件间通信有哪几种方式
- 你使用过 Vuex 吗
- 使用过 Vue SSR 吗?说说 SSR
- vue-router 路由模式有几种
- 能说下 vue-router 中常用的 hash 和 history 路由模式实现原理吗?
- 什么是 MVVM
- Vue 是如何实现数据双向绑定的
- Vue 框架怎么实现对象和数组的监听
- Proxy 与 Object.defineProperty 优劣对比
- Vue 怎么用 vm.$set() 解决对象新增属性不能响应的问题 ?
- 虚拟 DOM 的优缺点
- 虚拟 DOM 实现原理
- Vue 中的 key 有什么作用
- 你有对 Vue 项目进行哪些优化
- 对于即将到来的 vue3.0 特性你有什么了解的吗
- 说说你使用 Vue 框架踩过最大的坑是什么?怎么解决的