2023年vue面试题(持续更新中)

文章目录

  • 一、vue2和vue3双向数据绑定的原理区别
  • 二、vue2和vue生命周期钩子
  • 三、v-if和v-show的区别
  • 四、为何v-for要用key
  • 五、对mvvm的理解
  • 六、computed的特性
  • 七、组件中 data 为什么是一个函数?
  • 八、vue常见的性能优化
  • 八、自定义事件
  • 九、父子组件生命周期
  • 十、v-model实现
  • 十一、$nextTick
  • 十二、slot
  • 十三、动态组件
  • 十四、异步组件(什么时候用什么时候加载)
  • 十五、keep-live
  • 十六、mixin
  • 十七、Vuex使用
  • 十八、Vue-router
  • 十九、如何将组件所有props传递给子组件
  • 二十、何时需要使用beforeDestory
  • 二十一、Vuex中action和mutation有何区别
  • 二十二、请用vnode描述一个DOM结构
  • 二十三、Vue如何监听数组变化
  • 二十四、Vue如何监听数组变化
  • 二十五、diff算法的时间复杂度
  • 二十六、diff算法的过程
  • 二十七、Vue3比Vue2的优势
  • 二十七、Composition API对比 Options API
  • 二十八、如何理解ref toRef 和 toRefs
    • ref
    • toRef
    • toRefs
    • 最佳使用方式
    • 深入理解ref
  • 二十九、Vue3升级了哪些重要的功能
    • Composition API
  • 三十五、Vite为什么快?

一、vue2和vue3双向数据绑定的原理区别

Vue2的双向数据绑定原理:

Vue2的双向数据绑定主要是通过数据劫持和发布订阅模式实现的。

1.数据劫持:Vue2会用Object.defineProperty方法劫持每个属性的getter和setter,当数据发生变化时触发setter。

2.发布订阅模式:通过Dep(依赖)收集所有的Watcher(观察者),当数据变化后,通过Dep通知所有的Watcher,然后执行相应的视图更新函数。

如果模板中使用了这个数据,那么会被解析为一个Watcher,然后通过getter进行依赖收集,收集到Dep中。

这样,当数据发生变化时,就可以通过Dep通知到每个Watcher,然后更新视图。但是,由于Object.defineProperty的限制,Vue2无法检测到对象属性的添加或删除,以及数组的变化。

缺点:

  • 深度监听需要一次性递归
  • 无法监听新增删除属性
  • 无法原生监听数组,需要特殊处理

Vue3的双向数据绑定原理:

Vue3则是通过Proxy和Reflect这两个ES6的新特性来实现的双向数据绑定。

1.数据劫持:Vue3通过Proxy创建一个代理对象,来劫持用户的数据。

2.依赖收集:当我们把这个数据绑定在视图上时,Vue3会通过getter函数进行依赖收集,把当前的数据添加到对应的观察者列表中。

3.派发更新:当数据发生变化时,Vue3会通过setter函数,通知对应的观察者,然后观察者会去更新视图。

相比于Vue2,Vue3的双向数据绑定机制能够更好的处理数组和对象的变化,并且性能更优。

二、vue2和vue生命周期钩子

vue2生命周期钩子:

beforeCreate:实例刚在内存中被创建出来,还未初始化属性
created:实例已经创建完成,属性已经绑定,但DOM还未生成
beforeMount:模板已经编译完成,但还未挂载到页面中
mounted:模板已经挂载到页面中,用户已经可以看到渲染结果
beforeUpdate:数据发生变化,视图还未更新
updated:数据已经更新,视图也同步更新
beforeDestroy:实例销毁之前调用
destroyed:实例销毁后调用
activated – 被 keep-alive 缓存的组件激活时调用。
deactivated – 被 keep-alive 缓存的组件停用时调用

mounted 表示页面已经渲染完了,created页面还没有进行渲染,但是vue实例初始化了

vue3生命周期钩子

beforeCreate 和 created 在 Vue3 中被替换为 setup this指向为undefined

onBeforeMount – 在挂载开始之前被调用:相关的 render 函数首次被调用。
onMounted – 组件挂载时调用
onBeforeUpdate – 数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。
onUpdated – 由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
onBeforeUnmount – 在卸载组件实例之前调用。在这个阶段,实例仍然是完全正常的。
onUnmounted – 卸载组件实例后调用。调用此钩子时,组件实例的所有指令都被解除绑定,所有事件侦听器都被移除,所有子组件实例被卸载。
onActivated – 被 keep-alive 缓存的组件激活时调用。
onDeactivated – 被 keep-alive 缓存的组件停用时调用

三、v-if和v-show的区别

相同点:都可以控制dom元素的显示和隐藏

不同点:v-show只是改变display属性,dom元素并未消失,切换时不需要重新渲染页面,v-if直接将dom元素从页面删除,再次切换需要重新渲染页面

如果需要非常频繁地切换dom元素,v-show 更好,否则v-if 更好。

四、为何v-for要用key

快速查找到节点,减少渲染次数,提升渲染性能

五、对mvvm的理解

m->model(模型),v->view(视图),vm->viewModel(视图模型)。

当模型的数据发生变化时,视图模型会自动更新视图;当用户在视图中进行操作时,视图模型会自动更新模型的数据

六、computed的特性

缓存,data不变不会重新计算,提高性能

七、组件中 data 为什么是一个函数?

data选项被定义为函数而不是对象是为了确保每个Vue组件实例拥有独立的数据对象,避免数据共享问题,并方便访问组件实例的上下文。

八、vue常见的性能优化

使用异步组件:将页面划分为异步组件,根据需要按需加载,减少初始加载时间。

列表渲染优化:在使用v-for指令渲染列表时,使用key属性提供唯一标识符,以便Vue能够高效地更新和重用元素。

缓存计算属性:使用计算属性(computed)时,考虑使用缓存选项(cached: true)来缓存计算结果,避免不必要的重复计算。

合理使用v-if和v-show:根据情况选择合适的指令。v-if在条件为假时会销毁和重新创建元素,而v-show只是切换元素的显示和隐藏。如果需要频繁切换,使用v-show会更高效。

避免不必要的监听器:在使用watch监听数据变化时,确保只监听必要的数据,并避免监听大型、深层次的对象或数组。

利用v-once:对于静态内容,可以使用v-once指令使其只渲染一次,避免不必要的更新。

懒加载图片:对于大量图片或需要滚动加载的图片,可以使用懒加载技术,只在图片进入视口时再进行加载。

使用keep-alive:对于频繁切换的组件,使用keep-alive组件进行缓存,避免每次都销毁和重新创建组件。

使用合适的构建工具:在生产环境中,使用Webpack等构建工具进行代码压缩、代码分割和按需加载,以减小文件体积和提高加载速度。

八、自定义事件

// 绑定自定义事件
event.$on('xxx', this.add) //第二个参数为函数

// 调用自定义事件
event.$emit('xxx', this.title) //第二个参数传值

注意:event 为new Vue() 实例,绑定自定义事件第二个参数为函数的原因是因为在组件销毁的时候进行事件销毁,否则造成内存泄漏

// 销毁
event.$off('xxx', this.add) 

九、父子组件生命周期

创建以及渲染
father created -> son created -> son mounted -> father mounted

添加修改数据时,值传给子组件
father beforeUpdate -> son beforeUpdate -> son updated -> father updated

组件销毁时
father beforeDestroy -> son beforeDestroy -> son destroyed -> father destroyed

十、v-model实现

// 父组件
<MysonVmodel v-model="name" />
// 子组件
<template>
    <input type="text" :value="text1" @input="$emit('change',$event.target.value)">
template>
model: {
    prop: 'text1',
    event: 'change'
},
props: {
    text1: {
        type: String,
        default(){
            return ''
        }
    }
},

十一、$nextTick

  • Vue是异步渲染
  • data改变之后,DOM不会立刻渲染,(无论有多少data修改vue只异步渲染一次)
  • $nextTick会在DOM渲染之后被触发,以获取最新DOM节点

十二、slot

  • 基本使用:父组件往子组件插入一段内容
    2023年vue面试题(持续更新中)_第1张图片
    2023年vue面试题(持续更新中)_第2张图片

  • 作用域插槽

2023年vue面试题(持续更新中)_第3张图片
2023年vue面试题(持续更新中)_第4张图片

  • 具名插槽
    2023年vue面试题(持续更新中)_第5张图片

十三、动态组件

根据组件的名字进行渲染
在这里插入图片描述

  • :is=“component-name” 用法
  • 需要根据数据,动态渲染的场景。即组件类型不确定。

十四、异步组件(什么时候用什么时候加载)

  • import() 函数 应用:路由异步加载
    在这里插入图片描述在这里插入图片描述
  • 按需加载,异步加载大组件

十五、keep-live

  • 缓存组件 (tab切换)
  • 频繁切换,不需要重复渲染
  • Vue常见性能优化

十六、mixin

  • 多个组件有相同的逻辑,抽离出来
  • mixin并不是完美的解决方案,会有一些问题
    1.变量来源不明确,不利于阅读
    2.多mixin可能会造成命名冲突
    3.mixin和组件肯出现多对多的关系,复杂度较高
  • Vue3提出的Composition API旨在解决这些问题

十七、Vuex使用

vuex的基本使用

十八、Vue-router

  1. 路由模式:hash模式、h5 history模式(后端要配置,服务器就不返回404错误页面,前端需要配置)
    2023年vue面试题(持续更新中)_第6张图片

  2. 路由配置:动态路由、路由懒加载
    2023年vue面试题(持续更新中)_第7张图片

十九、如何将组件所有props传递给子组件

2023年vue面试题(持续更新中)_第8张图片

二十、何时需要使用beforeDestory

  1. 解绑自定义事件event.$off
  2. 清除定时器
  3. 解绑自定义DOM事件,如window scroll 等

二十一、Vuex中action和mutation有何区别

2023年vue面试题(持续更新中)_第9张图片

二十二、请用vnode描述一个DOM结构

2023年vue面试题(持续更新中)_第10张图片

二十三、Vue如何监听数组变化

2023年vue面试题(持续更新中)_第11张图片

二十四、Vue如何监听数组变化

2023年vue面试题(持续更新中)_第12张图片

二十五、diff算法的时间复杂度

  • o(n)
  • 在o(n3)基础上做了一些调整

二十六、diff算法的过程

2023年vue面试题(持续更新中)_第13张图片

二十七、Vue3比Vue2的优势

  • 性能更好
  • 体积更小
  • 更好的ts支持
  • 更好的逻辑抽离
  • 更好的代码组织
  • 更多新功能

二十七、Composition API对比 Options API

Composition API:更好的代码组织、更好的逻辑复用、更好的类型推导 (应对大型复杂的项目)
Options API:逻辑简单,小型项目可以使用
2023年vue面试题(持续更新中)_第14张图片

二十八、如何理解ref toRef 和 toRefs

ref

  1. 生成值类型的响应式数据
  2. 可用于模板和reactive
  3. 通过.value修改值

toRef

  1. 针对一个响应式对象(reactive封装)的prop(属性)
  2. 创建一个ref,具有响应式
  3. 两者保持引用关系

2023年vue面试题(持续更新中)_第15张图片

toRefs

  • 将响应式对象(reactive封装)转换为普通对象
  • 对象的每个prop(属性)都是对应的ref
  • 两者保持引用关系
    2023年vue面试题(持续更新中)_第16张图片

最佳使用方式

  • 用reactive做对象的响应式,用ref做值类型响应式
  • setup中返回toRefs(state),或者toRef(state,‘xxx’)
  • ref的变量命名都用xxxRef
  • 合成函数返回响应式对象时,使用toRefs

深入理解ref

为何需要ref:

  • 返回值类型,会丢失响应式
  • 在setup、computed、合成函数,都有可能返回值类型
  • Vue如不定义ref,用户将自造ref,反而混乱

为何需要.vale:

  • ref是一个对象(不丢失响应式),value存储值
  • 通过.value属性的get和set实现响应式
  • 用于模板、reactive时,不需要.value,其他情况都需要

为何需要toRef和toRefs:

  • 初衷:不丢失响应式的情况下,把对象数据分解、扩散、结构
  • 前提:针对的是响应式对象(reactive封装的)非普通对象
  • 注意:不创造响应式,而是延续响应式

二十九、Vue3升级了哪些重要的功能

  1. createApp

  2. emits属性

  3. 生命周期

  4. 多事件

  5. 移除.sync

  6. 异步组件的写法

  7. 移除filter

  8. Teleport

  9. Suspense
    10.Composition API

Composition API

  • 抽离逻辑代码到一个函数
  • 函数命名约定为userxxx格式(react hooks 也是)
  • 在setup中引用userxxx函数

三十五、Vite为什么快?

  1. 开发环境使用ES6 Module,无需打包 非常快

  2. 生产环境使用rollup,并不会快很多

你可能感兴趣的:(vue.js,javascript,前端)