1、简述 mixin、extends 的覆盖逻辑?
- mixin 和 extends均是用于合并、拓展组件的,两者均通过 mergeOptions 方法实现合并。
- mixins 接收一个混入对象的数组,其中混入对象可以像正常的实例对象一样包含实例选项,这些选项会被合并到最终的选项中。Mixin 钩子按照传入顺序依次调用,并在调用组件自身的钩子之前被调用。
- extends 主要是为了便于扩展单文件组件,接收一个对象或构造函数。
2、mergeOptions的执行过程?
- 规范化选项(normalizeProps、normalizelnject、normalizeDirectives)
- 对未合并的选项,进行判断
- 合并处理。根据一个通用 Vue 实例所包含的选项进行分类逐一判断合并,如 props、data、 methods、watch、computed、生命周期等,将合并结果存储在新定义的 options 对象里。
- 返回合并结果 options。
3、描述下Vue自定义指令?
- 在 Vue2.0 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。
- 一般需要对DOM元素进行底层操作时使用,尽量只用来操作 DOM展示,不修改内部的值。当使用自定义指令直接修改 value 值时绑定v-model的值也不会同步更新;如必须修改可以在自定义指令中使用keydown事件,在vue组件中使用 change事件,回调中修改vue数据
4、自定义指令钩子函数、参数?
- 全局定义:Vue.directive("focus",{})
- 局部定义:directives:{focus:{}}
- 钩子函数:指令定义对象提供钩子函数
- el:指令所绑定的元素,可以用来直接操作 DOM。
- binding:一个对象,包含以下 property:
- name:指令名,不包括 v- 前缀。
- value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2。
- oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
- expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中表达式为 "1 + 1"。
- arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"。
- modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
- vnode:Vue 编译生成的虚拟节点。
- oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
5、自定义指令使用场景?
- 普通DOM元素进行底层操作的时候,可以使用自定义指令
- 自定义指令是用来操作DOM的。尽管Vue推崇数据驱动视图的理念,但并非所有情况都适合数据驱动。自定义指令就是一种有效的补充和扩展,不仅可用于定义任何的DOM操作,并且是可复用的。
- 鼠标聚焦
- 下拉菜单
- 相对时间转换
- 滚动动画
6、Vue子组件可以直接改变父组件的数据吗?
- 不可以,
- 因为vue是单向数据流,数据流向从上到下,父级 props的更新向下流动到子组件,但是反过来则不行。这样防止从子组件意外变更父级组件的状态。子组件只能通过$emit派发一个自定义事件,父组件接收到后,由父组件修改。
7、Vue单向数据流?
- 在Vue中,单向数据流指的是数据从父组件流向子组件的单向过程。这意味着子组件不能直接修改从父组件接收的props数据,只能通过触发事件来通知父组件修改数据。这种数据流的方式是从上至下单向的,有利于数据的可预测性和可维护性。
8、为什么需要单向数据流?
- 可预测性: 由于数据是单向流动的,因此更容易理解和预测数据的变化。当数据变化时,你只需要关注数据的来源,而不需要追踪数据在多个组件之间的流动。
- 可维护性: 当数据流动是单向的,组件之间的依赖关系变得更加清晰。这使得代码更容易维护,因为修改一个组件通常只影响其下游组件,而不会影响其他不相关的组件。
- 简化组件间通信: 通过明确的数据流,开发者可以更容易地管理组件之间的通信。子组件通过事件通知父组件,这使得组件间通信更加明确和简单。
- 降低出错概率: 双向数据流可能会导致更复杂的错误,因为任何组件都可以修改数据,这可能导致数据的不一致性和不可预测的行为。单向数据流限制了直接修改数据的能力,从而减少了出错的机会。
- 促进最佳实践: 单向数据流鼓励将状态管理逻辑集中在一个地方(如Vuex),这有助于更好地组织和结构化代码,使得代码更加清晰和容易理解。
9、Vue是如何进行依赖收集的?
- 依赖收集是 Vue 实现响应式数据的核心。当组件被初始化时,Vue 会对组件的 data 进行初始化,将普通的 js 对象变成响应式对象。通过使用 Object.defineProperty 来实现,将属性转化为 getter/setter,在访问和修改属性时触发依赖收集和更新。
- 依赖收集的过程,在底层主要涉及到三个类:Dep、Watcher 和 Vue
- Dep 是依赖收集的核心,它的主要作用是管理所有的 Watcher。Dep 类中有一个静态属性 target,它指向当前正在计算的 Watcher,保证了同一时间全局只有一个 Watcher 被计算。Dep 类中还有一个 subs 属性,它是一个 Watcher 的数组,用来存储所有依赖这个 Dep 的 Watcher。
- Watcher 是一个用来计算表达式的类。在 Watcher 的构造函数中,它会执行表达式,这个表达式可能会触发数据的 getter,从而进行依赖收集。Watcher 类中还有一个 addDep 方法,它会将当前的 Watcher 添加到 Dep 的 subs 数组中。
- Vue 类是 Vue 的入口,它的主要作用是初始化 Vue 应用。在 Vue 类的初始化过程中,会对组件的 data 进行初始化,将普通的 JavaScript 对象变成响应式对象。在这个过程中,会进行依赖收集。
10、Vue的优点?
- 轻量级框架:只关注视图层,是一个构建数据的视图集合,大小只有几十 kb ;
- 简单易学:国人开发,中文文档,不存在语言障碍 ,易于理解和学习;
- 双向数据绑定:保留了 angular 的特点,在数据操作方面更为简单;
- 组件化:保留了 react 的优点,实现了 html 的封装和重用,在构建单页面应用方面有着独特的优势;
- 视图,数据,结构分离:使数据的更改更为简单,不需要进行逻辑代码的修改,只需要操作数据就能完成相关操作;
- 虚拟DOM:dom 操作是非常耗费性能的,不再使用原生的 dom 操作节点,极大解放 dom 操作,但具体操作的还是 dom 不过是换了另一种方式;
- 运行速度更快:相比较于 react 而言,同样是操作虚拟 dom,就性能而言, vue 存在很大的优