43.Vue 组件之间的通信方式都有哪些
⚫ 通过 props 传递:父组件传递数据给子组件
◼ 子组件设置 props 属性,定义接收父组件传递过来的参数
◼ 父组件在使用子组件标签中通过字面量来传递值
⚫ **通过$emit 触发自定义事件:**子组件传递数据给父组件
◼ 子组件通过emit 触发自定义事件,emit 第二个参数为传递的数值
◼ 父组件绑定监听器获取到子组件传递过来的参数
⚫ 使用 ref:
◼ 父组件在使用子组件的时候设置 ref
◼ 父组件通过设置子组件 ref 来获取数据
⚫ **EventBus:**兄弟组件传值
◼ 创建一个中央事件总线 EventBus
◼ 兄弟组件通过emit 触发自定义事件,emit 第二个参数为传递的数值
◼ 另一个兄弟组件通过$on 监听自定义事件
⚫ **parent 或root:**通过共同祖辈parent 或者root 搭建通信桥连
◼ 兄弟组件 this.parent.on('add',this.add) ◼ 另一个兄弟组件 this.parent.emit('add')
⚫ attrs 与 listeners
⚫ Provide 与 Inject
⚫ Vuex
44.你了解 vue 的 diff 算法吗?说说看
⚫ diff 算法是一种通过同层的树节点进行比较的高效算法
⚫ 两个特点:
◼ 比较只会在同层级进行, 不会跨层级比较
◼ 在 diff 比较的过程中,循环从两边向中间比较
⚫ 在 vue 中,作用于虚拟 dom 渲染成真实 dom 的新旧 VNode 节点比较
⚫ 当数据发生改变时,订阅者 watcher 就会调用 patch 给真实的 DOM 打补丁
⚫ 通过 isSameVnode 进行判断,相同则调用 patchVnode 方法
⚫ patchVnode做了以下操作:
◼ 找到对应的真实 dom,称为 el
◼ 如果都有文本节点且不相等,将 el 文本节点设置为 Vnode 的文本节点
◼ 如果 oldVnode 有子节点而 VNode 没有,则删除 el 子节点
◼ 如果 oldVnode 没有子节点而 VNode 有,则将 VNode 的子节点真实化后添加到 el
◼ 如果两者都有子节点,则执行 updateChildren 函数比较子节点
⚫ updateChildren主要做了以下操作:
◼ 设置新旧 VNode 的头尾指针
◼ 新旧头尾指针进行比较, 循环向中间靠拢
◼ 根据情况调用 patchVnode 进行 patch 重复流程、调用 createElement 创建一个新 节点,从哈希表寻找 key 一致的 VNode 节点再分情况操作
45.为什么需要 Virtual Dom,和真实 DOM 的区别是什么?
⚫ DOM 很慢,其元素非常庞大,页面的性能问题,大部分都是由 DOM 操作引起的
⚫ 真实的 DOM 节点,哪怕一个最简单的 div 也包含着很多属性
⚫ 虚拟 DOM 优势是 diff 算法,减少 JavaScript 操作真实 DOM 的带来的性能消耗。
⚫ 虚拟 DOM 最大的优势在于抽象了原本的渲染过程,实现了跨平台的能力,而不仅仅
局限于浏览器的 DOM,可以是安卓和 IOS 的原生组件,可以是近期很火热的小程序,也可以是各种 GUI
46.Vue3.0 的设计目标是什么?相比较 Vue2 来说做了哪些性****能优化?
⚫ 更小
◼ Vue3 移除一些不常用的 API
◼ tree-shaking,剔除无用模块,使打包的整体体积变小
⚫ 更快
◼ diff 算法优化
◼ 静态提升
◼ 事件监听缓存
◼ SSR 优化
⚫ 更友好
◼ vue3 兼顾 vue2 的 options API 同时还推出 composition API,增加了代码的逻辑组
织和代码复用能力
◼ vue3 是基于 typescipt 编写的,可以享受到自动的类型定义提示
⚫ 优化方案
◼ 源码
◆ 源码管理
⚫ 源码通过 monorepo 方式维护,根据功能将不同的模块拆分到 packages目录下面不同的子目录中
⚫ 一些 package(reactivity 响应式库)独立于 Vue 使用,用户只想使用 Vue3
的响应式能力,可以单独依赖这个响应式库而不用去依赖整个 Vue
◆ TypeScript
⚫ Vue3 基于 typeScript 编写,提供更好的类型检查,支持复杂的类型推导
◼ 性能
◆ 体积优化
◆ 编译优化
◆ 数据劫持优化
⚫ vue2 数据劫持通过 Object.defineProperty ,不检测对象属性添加和删除 ⚫ 尽管 Vue 提供了 set 和 delete 实例方法,但对于用户来说,增加负担
⚫ 面对嵌套层级比较深的情况下,就存在性能问题
⚫ vue3 通过 proxy 监听整个对象
⚫ Proxy 不能监听到内部深层次的对象变化,
⚫ 在 getter 去递归响应式,真正访问到的内部对象才会变成响应式
◼ 语法 API
◆ 优化逻辑组织
⚫ 相同功能代码编写在一块,不像 options API,各个功能的代码混成一块
◆ 优化逻辑复用
⚫ vue2:mixin 实现功能混合,多个 mixin 混合会命名冲突和数据来源不清晰
⚫ vue3:composition 将复用代码抽离出一个函数,使用的地方直接调用
47.Vue3.0 所采用的 Composition Api 与 Vue2.x 使用的****Options Api 有什么不同?
Options API(选项 API):
⚫ 定义 data,methods,computed,watch共同处理页面逻辑
⚫ 组件状态写在 data 属性上,方法写在 methods 属性上...
⚫ 当组件变得复杂,导致对应属性的列表也会增长,这会导致组件难以阅读和理解
Composition API(组合 API):
⚫ 根据逻辑功能来组织,一个功能所定义所有 API 放一起(更加的高内聚,低耦合)
⚫ 即使项目很大功能很多,我们都能快速的定位到这个功能所用到的所有 API
区别:
⚫ 逻辑组织和逻辑复用: Composition 将相关代码组织在一起,逻辑更容易地复用和测试。
⚫ 更好的类型推导: Composition 利用 TypeScript 的类型系统,提供了更好的类型推导
⚫ 更直观的代码结构: Composition 使用函数组织逻辑,使代码结构更加直观和清晰。
⚫ Composition API 对 tree-shaking 友好,代码也更容易压缩
⚫ Composition API 中没有 this,减少了 this 指向不明的情况
⚫ 更好的响应式系统: Composition 使用 reactive、ref 创建响应式数据,使得逻辑与状态
之间的关联更加明确和可追踪。
如果是小型组件,可以继续使用 Options API,也是十分友好的
48.说一下 Vue 数据响应式的原理,Vue2 和 Vue3 的有什么****区别?
⚫ 实现方式:
◼ Vue2:
◆ 使用 Object.defineProperty()方法来劫持对象的 getter 和 setter,以此来实现
数据的响应式。
◆ 对每个属性单独进行响应式转换 ◆ 不能监听数组的索引和长度属性的变化,无法监听新增或删除的属性。
◼ Vue3:
◆ 引入了 Proxy 对象,这是一种更全面的拦截器
◆ 直接代理整个对象,监听对象的所有属性变化,包括新增和删除属性,
◆ 同时也支持数组的变化。使用 Proxy 可以更高效地追踪变化,且代码更简洁。
⚫ 数组处理:
◼ Vue2:
◆ 通过重写数组的变异方法(如 push、shift 等)来实现数组的响应式,
◆ 但对于通过索引直接修改数组元素或修改数组长度的操作无法响应。
◼ Vue3:
◆ 利用 Proxy 和 Reflect,能够直接代理数组
◆ 可以捕获到所有形式的数组变更,包括直接修改数组元素和长度。
⚫ 新增特性和 API:
◼ Vue3 引入了新的 API,如 reactive 和 ref,使得对响应式对象和基本类型值的创建
更加直观和灵活。
◼ reactive用于创建深层次响应式对象
◼ ref主要用于包装基本类型值或对象,使其具有响应式特性。
⚫ 性能优化:
◼ Vue3 通过改进的依赖追踪系统(使用 track 和 trigger),提高了响应式的性能。
◼ 特别是在大型应用中,这些优化有助于减少不必要的更新,提升应用的整体性能。
⚫ 组件内部结构:
◼ Vue3 中引入了 Composition API,这是一种新的组织和复用代码的方式,鼓励使用
函数式编程风格,与原有的 Options API 并行存在,为开发者提供了更多灵活性。
49.Vue3 中的生命周期函数的变化以及含义
⚫ setup():
◼ beforeCreate 和 created 这两个生命周期钩子不再存在,被 setup()方法所取代。
◼ 状态的初始化、事件的绑定等,都会在 setup()方法中进行配置
⚫ 挂载阶段:
◼ beforeMount 和 mounted 保留,但使用 onBeforeMount 和 onMounted 定义逻辑。
◼ onBeforeMount 挂载之前调用,准备工作
◼ onMounted 挂载之后调用,挂载之后调用
⚫ 更新阶段:
◼ beforeUpdate 和 updated 依然存在,但推荐使用 onBeforeUpdate 和 onUpdated。
◼ onBeforeUpdate 进行一些状态的保存或准备工作
◼ onUpdated 更新之后调用,可以进行一些操作,比如获取更新后的 DOM 状态、执行一些更新后的逻辑等。
beforeDestroy 和 destroyed 被重命名为 beforeUnmount 和 unmounted,任何组件卸载前的
清理工作,如清除定时器或解绑全局事件