vue面试题

196 阅读9分钟

1.vue组件中data为什么是函数

在 Vue 组件中,data 是一个函数的原因是为了实现组件的局部作用域和防止数据冲突。

每个 Vue 组件都应该具有一个独立的 data 函数,该函数返回一个对象,该对
象包含了该组件的响应式数据。通过将 data 函数定义为函数,可以确保每个组件都有
自己的数据副本,而不是共享全局数据。这样可以避免数据冲突和意外修改其他组件的
数据。

此外,通过将 data 函数定义为函数,还可以在组件实例化时生成新的数据对象。这意
味着每次渲染组件时,都会使用新的数据对象,从而确保组件的状态始终是最新的。

总结起来,将 data 函数定义为函数的好处包括:

实现组件的局部作用域:每个组件都有自己的数据副本,避免数据冲突。
生成新的数据对象:每次渲染组件时都会使用新的数据对象,确保状态始终是最新的。

2.vue3 watch和watchEffect的区别

在 Vue 3 中,watch 和 watchEffect 都是用于观察和响应组件的数据变化的工具,
但它们之间存在一些关键差异。

·执行时机:watch 是惰性执行的,即只有当监听的值发生变化时才会执行。而
watchEffect 在每次代码加载时都会执行。
·参数需求:watch 需要传递监听的对象,而 watchEffect 则不需要。
数据类型:watch 只能监听响应式数据,如 ref 定义的属性和 reactive 定义的对
象。如果直接监听 reactive 定义对象中的属性,这是不允许的,除非通过函数进行转
换。相比之下,watchEffect 可以监听对象中的属性,但不能直接监听整个对象。
·性能考量:watchEffect 在副作用发生期间追踪依赖,自动追踪所有能访问到的响应
式属性。这使得代码更简洁,但有时其响应性依赖关系可能不那么明确。相反,watch 
更精确地控制回调函数的触发时机,从而避免在发生副作用时追踪依赖。
获取新旧值:在使用 watchEffect 时,我们无法获取新值(newVal)和旧值(oldVal)
。
总结:选择 watch 或 watchEffect 应基于具体的使用场景和需求。如果需要在数据
变化时执行某些操作,并且希望避免不必要的计算或函数调用,那么 watch 可能是更好的
选择。而如果需要在每次组件渲染时执行某些操作,或者希望自动追踪响应式属性,那么
watchEffect 可能更合适。

3.vue2和vue3中的v-if和v-for的区别

在 Vue 2 和 Vue 3 中,v-if 和 v-for 指令有以下几点区别:

优先级:在 Vue 2 中,v-for 的优先级比 v-if 高,这意味着 v-if 将在每个
v-for 循环中分别重复运行。而在 Vue 3 中,v-if 的优先级更高。这意味着当它们
同时存在于一个节点上时,v-if 将先执行。
使用场景:Vue 2 中的 v-if 可以被用于有条件地跳过循环的执行,可以将 v-if 置
于外层元素(或 <template>)上。而在 Vue 3 中,由于 v-if 的优先级更高,这样
的用法可能会导致问题。

4.vue3的生命周期

Vue 3的生命周期钩子函数包括:
beforeCreate:在实例被创建之初,响应式数据和事件尚未初始化。
created:实例创建完毕,响应式数据和事件已初始化。
beforeMount:模板编译/渲染开始前执行。
mounted:模板编译/渲染完毕,组件实例挂载到DOM上。
beforeUpdate:数据更新前执行。
updated:数据更新完毕。
beforeUnmount:组件卸载前执行。
unmounted:组件卸载完毕。

在 Vue3 中,beforeDestroy 和 destroyed 这两个钩子函数已经被废弃,而是使用 
beforeUnmount 和 unmounted 替代。

在 Vue3 中,生命周期钩子函数的执行顺序如下:
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
beforeUnmount
unmounted

除了前文提到的生命周期钩子函数外,Vue3 还提供了如下生命周期钩子函数:

activated:在 keep-alive 组件激活时调用;
deactivated:在 keep-alive 组件停用时调用;
errorCaptured:在捕获子组件错误时调用。

5.vue3新增了哪些api

Vue 3  API 层面上有以下主要的新增和改进:

Composition API: 提供了更灵活的方式来组合组件的逻辑,主要通过 setup 函数
、ref、reactive、computed  watch 等新的 Composition API 函数。

Fragment: 支持使用 <Fragment> 组件来代替 <div> 标签,可以避免不必要的 DOM 
层级。

Teleport: 提供了 <Teleport> 组件,可以将组件的子节点传送到 DOM 中的一个不
同位置。

Emits Options: 组件现在可以指定 emits 选项,以强制组件用户使用指定的事件名。

Fragments and Multiple Root Nodes: 组件现在可以包含多个根节点,不再强制
只能有一个根节点。

Composition API 改进: 提供了 watch  watchEffect 函数,以及新的 provide 
 inject 函数,用于更灵活的依赖注入。

Custom Renderer API: 自定义渲染器 API 允许 Vue 在不同平台上渲染,例如 Web 
 WeChat小程序。

Suspense: 通过 <Suspense> 组件,可以处理异步组件的加载中和失败状态。

Script Setup: 使用 <script setup> 可以进一步简化组件的声明式编写。

Other Improvements:  SSR 改进、更好的 TypeScript 支持、更高效的渲染
机制等。

6.vue3中Teleport使用

Vue 3 的 Teleport 是一种新的功能,允许开发者将一个组件渲染到 DOM 树中的任何
位置,而不必将其作为 Vue 实例中的子组件放置在静态位置。这为构建更灵活的用户界
面提供了极大的便利。

使用 Teleport 的主要场景是解决组件逻辑位置与 DOM 位置不一致的问题。例如,
一个全屏的弹出框或 Toast 轻提示组件可能会在多个组件中使用到,但是由于节点嵌套
的太深,我们想把它的 DOM 元素放在最外层的容器上面。此时,Teleport 就派上了用
。通过将这类组件放置在 Teleport 组件中,我们可以指定该组件渲染到父组件之外的
其它 DOM 节点下,如 body 或其它 DOM 元素。

Teleport 的基本用法很简单,它接受两个参数:要渲染的组件和一个目标 DOM 元素或
选择器。我们只需要将需要渲染的组件作为第一个参数传递给 Teleport,并将一个 
DOM 元素或选择器作为第二个参数传递给它,Teleport 就会将组件渲染到该位置。

值得注意的是,使用 Teleport 可以避免样式污染,并使得处理嵌套组件的定位、
z-index 和样式变得更加简单。同时,它提供了一种更高效、更直观的方法来实现灵活
的组件渲染,无需像传统的 Vue 组件那样始终在同一位置。


<template>  
  <div>  
    <button @click="showModal = true">打开模态框</button>  
    <Teleport to="body">  
      <Modal v-if="showModal" @close="showModal = false">  
        <!-- 模态框内容 -->  
      </Modal>  
    </Teleport>  
  </div>  
</template>  
  
<script>  
import { Teleport, Modal } from 'vue';  
  
export default {  
  components: {  
    Teleport,  
    Modal,  
  },  
  data() {  
    return {  
      showModal: false,  
    };  
  },  
};  
</script>

7.vue3 computed

Vue 3 中,computed 是一个用于创建计算属性的 API。计算属性是基于它们的响应
式依赖进行缓存的,只有当依赖发生改变时才会重新计算。这使得计算属性比方法
(methods)更加高效,特别是当计算过程比较耗时或依赖其他响应式数据时。

计算属性可以通过 computed 函数来创建,该函数返回一个响应式的引用,可以像普通属
性一样在模板中使用。

下面是一个 Vue 3 中使用 computed 的例子:

vue
<template>  
  <div>  
    <p>原始数值: {{ number }}</p>  
    <p>计算后的数值: {{ doubledNumber }}</p>  
  </div>  
</template>  
  
<script>  
import { ref, computed } from 'vue';  
  
export default {  
  setup() {  
    // 创建一个响应式的数值  
    const number = ref(5);  
  
    // 创建一个计算属性,该属性将数值翻倍  
    const doubledNumber = computed(() => {  
      return number.value * 2;  
    });  
  
    // 返回响应式数据和计算属性  
    return {  
      number,  
      doubledNumber,  
    };  
  },  
};  
</script>
在这个例子中,number 是一个响应式的数值,我们使
用 ref 来创建它。然后,我们使用 computed 来创建一个计算属性 doubledNumber,
它将 number 的值翻倍。在模板中,我们可以像使用普通属性一样使用 doubledNumber。

注意,在 computed 函数中,我们通过 number.value 来访问 number 的值,因为
 ref 创建的是一个包含 value 属性的响应式对象。

计算属性还可以具有 setter,允许你在计算属性值被修改时执行自定义逻辑。但是,
在 Vue 3Composition API 中,setter 的使用相对较少,因为你可以直接使用 
watchEffect 或 watch 来观察和响应数据的变化。如果你确实需要 setter,你可以
使用computed 的一个变种 writableComputed(可能需要第三方库或自定义实现)
,但 Vue 官方推荐尽可能避免在计算属性中使用 setter。

8.vue3为什么使用proxy

1.动态代理:Proxy 可以直接监听对象而非属性,这意味着它可以跟踪整个对象及其所
有属性和方法的变动,而不仅仅是特定的属性或方法。
2.兼容性:虽然 ProxyECMAScript 2015(ES6)引入的标准,但它仍然提供了
良好的浏览器兼容性,至少支持到 IE9。相比之下,Object.defineProperty 虽然
功能强大,但由于其设计上的限制,它在某些情况下可能无法工作,尤其是在旧版本的
浏览器中。

3.性能优化:Proxy 作为一种新标准,可能会在未来得到浏览器厂商的重点性能优化,
从而提高开发效率并降低内存占用。

4.响应式系统的实现:在 Vue.js 2.x 中,响应式系统的实现依赖于 
Object.defineProperty 对数据源的属性设置 getter 和 setter。这种方法
对于预定义的属性有效,但对于未预定义的属性则无法正确处理。Proxy 通过提供一个
拦截器,可以在目标对象之前架设一层“拦截”,允许开发者在外界访问目标对象
时对其进行过滤和改写,从而实现在不需要手动设置 getter 和 setter 的情况下
也能实现响应式系统。