vue3最新面试题

发布时间:2024-05-21 12:45:16

vue3 响应式原理 和 vue2 的区别?

vue2.x的响应式:

对象类型:通过Object.defineProperty()对属性的读取、修改进行拦截(数据劫持)。

数组类型:通过重写更新数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)。

存在问题:

新增属性、删除属性, 界面不会更新。

直接通过下标修改数组, 界面不会自动更新。

vue3.0的响应式:

实现原理:

通过Proxy(代理): 拦截对象中任意属性的变化, 包括:属性值的读写、属性的添加、属性的删除等。

通过Reflect(反射): 对源对象的属性进行操作。

Object.defineProperty 和 Proxy 的区别?

Object.defineProperty 是 es5 的方法。Proxy 是 es6 的方法

Object.defineProperty 不能监听到数组下标变化和对象新增属性。Proxy 可以

Object.defineProperty 是劫持对象属性。Proxy 是代理整个对象

Object.defineProperty 是递归遍历对象属性,只能监听单个属性。Proxy 对象嵌套属性运行时递归,用到的时候再进行代理,也不需要维护特别多的依赖关系,性能提升很大,且首次渲染更快

Object.defineProperty 会污染原对象,修改时是修改原对象。Proxy 是对原对象进行代理并会返回一个新的代理对象,修改的是代理对象

Object.defineProperty 不兼容 IE8。Proxy 不兼容 IE11

谈谈你对 setup 函数的了解?

setup 会在 beforeCreate() 之前执行

setup 不能使用 this

setup 内部的属性、方法,必须 return 暴露出来。否则没法使用

setup 内部数据不具有响应式

setup 不能调用生命周期相关函数,但生命周期函数可以调用 setup 内的函数

setup 方法和 setup 语法糖的区别?

// 方法setup(props.context) {}

// 语法糖<script setup></script>

ref 和 reactive 区别?

定义数据:

ref 通常用来定义基本类型数据,也可以传入引用类型的数据,内部会通过 reactive 转化为代理对象,只是不推荐这么做

reactive 用来定义引用类型数据

实现原理:

ref 通过Object.defineProperty来实现数据代理

reactive 使用 proxy 实现数据代理,并且通过 reflect 操作原对象内部的数据

操作数据:

ref 在 js 中,获取和修改数据需要 .value,template 中不需要

reactive 不需要


toRef:针对一个响应式对象的属性创建一个ref,使得该属性具有响应式,两者之间保持引用关系。(入下所示,即让state中的age属性具有响应式)

toRefs:将一个响应式对象转为普通对象,对象的每一个属性都是对应的ref,两者保持引用关系

reactive 可以创建基本类型的(单一值)响应式数据么?

不可以传入基本类型数据,如果传入则不会返回proxy对象,由于reactive是基于proxy实现响应式的,如果返回的不是proxy对象,则该数据不会具有响应式。

怎么重置 reactive 数据?

第一种:

import { reactive } from 'vue'

class InitFormData {
  userName: string = ''
  age: number = 0
}

let formData = reactive(new InitFormData())

// 重置数据
Object.assign(formData, new InitFormData())

第二种:

import { reactive } from 'vue'

const initFormData = () => {
  return {
    userName: '',
    age: 0
  }
}

let formData = reactive(initFormData())

// 重置数据
Object.assign(formData, initFormData())

第三种:

import {reactive} from 'vue'

const initFormData = {
  userName: '',
  age: 0
}

const _initFormData = Object.assign({}, initFormData)

let formData = reactive{formData: initFormData}

// 重置数据
formData.formData = Object.assign({}, _initFormData)

vue3的常用 Composition API有哪些?

setup
ref函数
reactive函数
computed函数
watch函数
watchEffect函数
toRef
shallowReactive 与 shallowRef
readonly 与 shallowReadonly
readonly: 让一个响应式数据变为只读的(深只读)。
shallowReadonly:让一个响应式数据变为只读的(浅只读)。
toRaw 与 markRaw
customRef
provide 与 inject

vue3响应式数据的判断?

isRef: 检查一个值是否为一个 ref 对象
isReactive: 检查一个对象是否是由 reactive 创建的响应式代理
isReadonly: 检查一个对象是否是由 readonly 创建的只读代理
isProxy: 检查一个对象是否是由 reactive 或者 readonly 方法创建的代理

vue3中的事件修饰符有哪些?

.stop:阻止事件冒泡

.prevent:阻止默认事件行为

.capture:使用事件捕获模式

.self:只有当事件在元素本身(而不是子元素)触发时触发回调

.once:事件只触发一次

.left:只当鼠标左键被点击时触发

.right:只当鼠标右键被点击时触发

.middle:只当鼠标中键被点击时触发

.passive:以 { passive: true } 模式调用 eventListener

vue3中的指令有哪些?

vue3中的指令包括v-if、v-for、v-bind、v-on、v-html、v-model、v-show、v-slot、v-text等。

vue3中如何实现动态组件?

vue3中使用 <component> 元素和 v-bind:is 属性来实现动态组件。例如, <component v-bind:is="currentComponent"></component> 

watch(),watchEffect(),computed()的区别?

三者都用于实现数据和监听函数的绑定。原理上来说,三者的共同点是,都会在setup期间、即onBeforeMount之前,创建一个Effect对象,并执行依赖收集函数进行依赖收集。区别是,第一,watchEffect、computed的依赖收集函数和监听函数是同一个函数,而watch的依赖收集函数和回调函数是两个函数,这就导致了watchEffect和computed参数中的监听函数会在程序初始化期间执行一次,而watch参数中的监听函数默认不会执行;第二,computed参数中的监听函数在变量发生变化后立即执行,watchEffect、watch参数中的监听函数执行时机可由用户指定,可以立即执行,也可以异步执行。

vue3中的watch和watchEffect有何不同?

watch 允许你监听特定的响应式引用或计算属性,并在它们改变时执行回调函数。

watchEffect 会立即执行一个函数,并自动追踪其依赖的响应式引用,当依赖改变时重新执行。

1)watch和watchEffect都是vue3中的监听器,但是在写法和使用上是有区别的,主要是介绍一下watch和watchEffect的使用方法以及他们之间的区别。

2)watch 的工作原理:侦听特定的数据源,并在回调函数中执行副作用。它默认是惰性的——只有当被侦听的源发生变化时才执行回调,不过,可以通过配置immediate为true来指定初始时立即执行第一次。可以通过配置 deep 为 true,来指定深度监视。

3)immdiate:默认情况下,侦听器需要 data 后面值改变了才会生效,若需要侦听器一进入页面就生效,那就需要使用 immediate。

4)deep:默认情况下,侦听器只会监听数据本身的改变,若要进行深度监听,那就需要使用 deep。 

5、immediate 和 deep 配置在第三个参数对象里。 第一个参数:监听谁;第二个参数:回调函数;第三个参数:配置对象。

watchEffect 函数的特点:

优点:会自动收集依赖,不需要手动传递侦听内容——自动侦听回调函数中使用到的响应式数据。默认 immdiate 是 true,所以初始化时会立即执行。

缺点:无法获得变化前的值(oldVal)。

1)watch() 是懒执行的:当数据源发生变化时,才会执行回调。但在某些场景中,我们希望在创建侦听器时,立即执行一遍回调。

2)watchEffect相当于将watch 的依赖源和回调函数合并,当任何你有用到的响应式依赖更新时,该回调函数便会重新执行。不同于 watch,watchEffect 的回调函数会被立即执行(即 { immediate: true })。

3)简单来说,watchEffect是vue3中的一个响应式API,它允许你监听响应式状态的变化,并在其发生变化时触发副作用函数。这个特性非常有用,在我们需要对响应式数据进行操作的时候,我们可以在监听到变化后马上做出反应。

ref()和ref(null)的区别?

ref()的作用是封装普通数据,实现响应式数据;ref(null)的作用是获取子组件实例。

attrs和props的区别?

attrs和props的作用都是,以模板属性的形式,从父组件传递数据给子组件。区别是,子组件中获取从父组件传过来的props数据,首先需要用defineProps()声明,而获取attrs数据不需要声明。props的优势是增加了代码可读性,attrs的优势是传值更灵活、代码更简洁。

v-for为什么要加key?v-for为什么不能和v-if一起使用?

v-for要加key是因为,第一,vue的同步算法采用就地复用的策略,在没有key值的情况下,diff算法认为标签类型相同的元素可以进行复用;有key值的情况下,diff算法认为标签类型相同且key值相等的元素才可以复用。第二,vue只在v-model实现了数据双向绑定,其它地方实现的都是单向绑定,<input/>框内的文字发生变化,不会实时同步到数据上。

在vue3中,v-if的优先级高于v-for,导致v-if访问不了v-for中的变量,因此不能把 v-if 和 v-for 同时用在同一个元素上。

vue3如何优化性能?

使用v-show代替v-if来频繁切换元素,因为v-show只是切换元素的CSS属性。

使用key来优化列表渲染的性能。

使用computed和watch来减少不必要的计算和渲染。

使用v-memo来缓存组件的渲染结果。

EventBus与mitt区别?

vue2 中我们使用 EventBus 来实现跨组件之间的一些通信,它依赖于 vue 自带的 $on/$emit/$off 等方法,这种方式使用非常简单方便,但如果使用不当也会带来难以维护的毁灭灾难。

而 vue3 中移除了这些相关方法,这意味着 EventBus 这种方式我们使用不了, vue3 推荐尽可能使用 props/emits、provide/inject、vuex 等其他方式来替代。

当然,如果 vue3 内部的方式无法满足你,官方建议使用一些外部的辅助库,例如:mitt。

优点:

非常小,压缩后仅有 200 bytes。

完整 TS 支持,源码由 TS 编码。

跨框架,它并不是只能用在 Vue 中,React、JQ 等框架中也可以使用。

使用简单,仅有 on、emit、off 等少量实用API。

vite 开启 gzip 打包

安装:

npm i vite-plugin-compression

vite.config.js 配置:

import viteCompression from 'vite-plugin-compression'
const plugins = [
  vue(),
  vueJsx(),
  viteCompression({
    threshold: 10 * 1024 // 对大于10K的文件进行压缩
  })
]