vue 进阶面试题

197 阅读3分钟

vue2与vue3中生命周期执行顺序区别

  • vue2中执行顺序beforeCreate=>created=>beforeMount=>mounted=>beforeUpdate=>updated=>beforeDestroy=>destroyed

创建前/后:在beforeCreate阶段,vue实例的挂载元素el和数据对象data都为undefined,未初始化。 created阶段,vue实例的数据对象data有了,el为undefined,未初始化。

载入前/后:beforeMount阶段,vue实例的$el和data初始化,但还是挂载之前为虚拟的dom节点,data.message未替换。 mounted阶段:vue实例挂载完成,data.message成功渲染

更新前/后:data变化时,会触发beforeUpdate和updated方法 销毁前/后:在执行destory方法后,data的改变不会再触发周期函数,vue实例已解除了事件监听和dom绑定。但是dom结构还存在

  • vue3中执行顺序 setup=>onBeforeMount=>onMounted=>onBeforeUpdated=>onUpdated=>onBeforeUnmount=>onUnmounted
  • setup() :开始创建组件之前,在beforeCreate和created之前执行。创建的是data和method
  • onBeforeMount() : 组件挂载到节点上之前执行的函数。
  • onMounted() : 组件挂载完成后执行的函数。
  • onBeforeUpdate(): 组件更新之前执行的函数。
  • onUpdated(): 组件更新完成之后执行的函数。
  • onBeforeUnmount(): 组件卸载之前执行的函数。
  • onUnmounted(): 组件卸载完成后执行的函数
  • onActivated(): 被包含在中的组件,会多出两个生命周期钩子函数。被激活时执行。
  • onDeactivated(): 比如从 A 组件,切换到 B 组件,A 组件消失时执行。
  • onErrorCaptured(): 当捕获一个来自子孙组件的异常时激活钩子函数。 区别: setup相当于vue2中beforeCreate与created,但是执行是在beforeCreate与created之前。所以setup无法使用data和methods中的数据和方法,无法操作this.setup中创建的变量与方法最后都要通过return返回出去,所以setup是同步的

父子组件生命周期调用顺序?

  • 渲染顺序:先父后子,完成顺序;先子后父
  • 更新顺序:父更新导致子更新,子更新完成后父更新
  • 销毁顺序:先父后子,完成顺序,先子后父

vuex工作原理

vuex是为vue提供全局状态管理,用于多个组件中数据共享、数据缓存。 内部核心原理就是通过创造一个全局实例new Vue. 主要包括一下几个模块:

  • State:定义了应用状态的数据结构,可以在这里设置默认的初始状态

  • Getter:允许组件从 Store 中获取数据,mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性。

  • Mutation:是唯一更改 store 中状态的方法,且必须是同步函数。

  • Action:用于提交 mutation,而不是直接变更状态,可以包含任意异步操作。

  • Module:允许将单一的 Store 拆分为多个 store 且同时保存在单一的状态树中。

action与mutation的区别

  • mutation是同步更新,$watch严格模式下会报错
  • action是异步操作,可以获取数据后调用mutation提交最终数据

vue-router路由模式原理

  • hash 模式 原理:location.hash
    • location.hash的值实际就是URL中#后的内容,hash改变时,并会触发响应的hashchange事件。缺点在于:hash虽然出现URL中,但不会被包含在HTTP请求中,对后端完全没有影响,因此改变hash不会重新加载页面
    • 可以为hash的改变添加监听事件
  • history模式
    • 利用H5 History interface中新增的pushState()和replaceState()方法
    • 这两个方法有个共同的特点:当调用他们修改浏览器历史记录栈后,虽然当前URL改变了,但浏览器不会刷新页面。

diff算法

  • 原理简单说(对前后的节点树同一层的节点进行对比,一层一层的对比)
  • 原理:在数据发生变化时,vue是先根据真实DOM生成一颗Virtual Dom ,当Virtual DOM 某个节点的数据改变后生成一个新的Vnode,然后Vnode和oldVnode作对比,发现不一样的地方就直接修改在真实的DOM上,然后oldVnode的值为Vnode,实现更新节点。
  • 原理简述:patch方法和updateChildren方法
    • 先去同级比较,然后再去比较子节点
    • 先去判断一方有子节点,一方没有子节点的情况
    • 比较都有子节点的情况
    • 递归比较子节点 Diff算法只会比较同一层级的节点:
  • 如果节点类型不同,直接干掉前面的节点,再创建并插入新的节点
  • 如果节点类型相同,则会重新设置该节点的属性,从而实现节点的更新

vue如何监听对象或数组某个属性的变化?

  • this.$set(需要改变数组/对象,要改变的位置/key,改成什么value)
this.$set(this.arr,0,'nihao')// 改变数组
this.$set(this.obj,'c','nihao')// 改变对象
  • vue提供改写数组的7个方法:push、 pop、 shift、 unshift、 sort、 splice、 reverse

原理:

  • 数据初始化时调用initData方法,通过new Observer对数据进行检测
    • 如果是数组,判断是否支持原型链,支持就执行protoAugment让目标原型链指向arrayMethods,改写数组的原型方法。
    • 如果没有原型链就会走def方法添加__ob__属性
  • 采用函数劫持的方式,调用(push pop shift unshift sort splice reverse)方法,还会调用原数组的方法进行更新数组
  • 通过dep.notify通知视图更新

Vue.set方法原理

因为响应式数据 我们给对象和数组本身都增加了__ob__属性,代表的是 Observer 实例。当给对象新增不存在的属性 首先会把新的属性进行响应式跟踪 然后会触发对象__ob__的 dep 收集到的 watcher 去更新,当修改数组索引时我们调用数组本身的 splice 方法去更新数组。