Vue3 前端面试常见 20 道面试题总结(含详细代码解析)

1. Vue3 中 Composition API 的优势是什么?


Vue3 中引入了 Composition API,使得代码组织更加灵活,解决了 Vue2 中基于 Options API 的一些问题,如:

  • 逻辑复用性差:Vue2 中的逻辑复用通过 mixins 或者 slots 等方式,代码可维护性较差。
  • 组件中有很多逻辑时,数据和方法会分散在不同的地方,不易管理。

优势

  • 使逻辑复用变得更加简单,setup() 函数中封装逻辑,多个组件可以复用。
  • 提供了更强的类型推导支持,特别适用于 TypeScript。
  • 使得代码更加结构化和模块化,特别是当组件变得复杂时。
// Composition API 示例
import { ref, reactive, computed, watch } from 'vue'

export default {
  setup() {
    const count = ref(0)
    const state = reactive({ message: 'Hello Vue3' })
    
    const increment = () => {
      count.value++
    }

    // computed 示例
    const doubleCount = computed(() => count.value * 2)
    
    // watch 示例
    watch(count, (newValue, oldValue) => {
      console.log('count changed from', oldValue, 'to', newValue)
    })

    return {
      count,
      state,
      increment,
      doubleCount
    }
  }
}

2. Vue3 和 Vue2 的响应式系统有何区别?


Vue3 的响应式系统基于 Proxy,而 Vue2 是基于 Object.defineProperty。这带来了以下区别:

  • 性能:Vue3 在处理大量的数据和复杂的嵌套对象时性能更优,因为 Proxy 可以直接操作对象的所有属性,而 Vue2 需要为每个属性单独定义 getter 和 setter。
  • 支持动态添加/删除属性:Vue3 的 Proxy 可以检测到动态添加或删除的属性,而 Vue2 在这方面有一些局限。
  • API 的简化:Vue3 使用了 ref() 和 reactive() 等简化的 API。
// Vue3 响应式示例
import { reactive, toRefs } from 'vue'

export default {
  setup() {
    const state = reactive({
      count: 0,
      name: 'Vue3'
    })

    return {
      ...toRefs(state)  // 用于解包响应式对象,避免引用错误
    }
  }
}

3. Vue3 中如何创建一个动态组件?


动态组件可以使用 component 标签和 v-bind 或 v-model 来动态加载不同的组件。

<template>
  <component :is="currentComponent" />
</template>

<script setup>
import { ref } from 'vue'
import ComponentA from './ComponentA.vue'
import ComponentB from './ComponentB.vue'

const currentComponent = ref(ComponentA)

// 动态切换组件
setTimeout(() => {
  currentComponent.value = ComponentB
}, 3000)
</script>

4. Vue3 如何实现父子组件通信?

  • 父组件向子组件传递数据:使用 props
  • 子组件向父组件传递数据:使用 emit 事件。
<!-- 父组件 -->
<template>
  <ChildComponent :message="parentMessage" @childEvent="handleChildEvent" />
</template>

<script setup>
import { ref } from 'vue'
import ChildComponent from './ChildComponent.vue'

const parentMessage = ref('Hello from Parent')

const handleChildEvent = (data) => {
  console.log('Received from child:', data)
}
</script>

<!-- 子组件 -->
<template>
  <button @click="sendToParent">Send to Parent</button>
</template>

<script setup>
import { defineProps, defineEmits } from 'vue'

defineProps(['message'])
const emit = defineEmits()

const sendToParent = () => {
  emit('childEvent', 'Hello from Child')
}
</script>

5. Vue3 中如何使用 v-model


在 Vue3 中,v-model 默认绑定 value,并且可以通过 modelValue 修改。

<!-- 父组件 -->
<template>
  <ChildComponent v-model="message" />
</template>

<script setup>
import { ref } from 'vue'
import ChildComponent from './ChildComponent.vue'

const message = ref('Hello World')
</script>

<!-- 子组件 -->
<template>
  <input v-model="modelValue" />
</template>

<script setup>
import { defineProps, defineEmits } from 'vue'

const props = defineProps({
  modelValue: {
    type: String,
    default: ''
  }
})

const emit = defineEmits()

// 当 input 变化时同步 modelValue
watch(() => props.modelValue, (newValue) => {
  emit('update:modelValue', newValue)
})
</script>

6. Vue3 中如何实现懒加载组件?


使用 Vue 的异步组件功能来实现懒加载。通过 defineAsyncComponent 或 import() 实现。

import { defineAsyncComponent } from 'vue'

export default {
  components: {
    AsyncComponent: defineAsyncComponent(() => import('./AsyncComponent.vue'))
  }
}

7. Vue3 如何使用 watch 和 watchEffect

  • watch 用于观察指定的数据源,并在数据变化时执行副作用。
  • watchEffect 会立即执行并自动跟踪响应式依赖。
import { ref, watch, watchEffect } from 'vue'

const count = ref(0)

watch(count, (newValue, oldValue) => {
  console.log('count changed from', oldValue, 'to', newValue)
})

watchEffect(() => {
  console.log('This is tracked:', count.value)
})

setTimeout(() => {
  count.value = 5
}, 2000)

8. 如何在 Vue3 中使用 provide 和 inject

  • provide 和 inject 用于跨组件层级传递数据,解决了 Vue2 中的 “prop drilling” 问题。
// 父组件
<template>
  <Child />
</template>

<script setup>
import { provide } from 'vue'

provide('message', 'Hello from Parent')
</script>

<!-- 子组件 -->
<template>
  <div>{{ message }}</div>
</template>

<script setup>
import { inject } from 'vue'

const message = inject('message')
</script>

9. Vue3 中如何创建一个自定义指令?


可以使用 app.directive() 来全局注册自定义指令,也可以使用 v-bind 动态传递。

// 全局注册
import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)

app.directive('focus', {
  mounted(el) {
    el.focus()
  }
})

app.mount('#app')

10. Vue3 中如何使用 teleport 进行跨层级渲染?


teleport 用于将组件的内容渲染到 DOM 树的不同位置。

<template>
  <teleport to="body">
    <div class="modal">
      <p>This is a modal</p>
    </div>
  </teleport>
</template>

11. 如何在 Vue3 中处理异步操作?


Vue3 推荐使用 async 和 await 来处理异步操作,配合 watchEffect 或生命周期钩子。

import { ref, onMounted } from 'vue'

const data = ref(null)

onMounted(async () => {
  const response = await fetch('https://api.example.com/data')
  data.value = await response.json()
})

12. Vue3 的 Suspense 组件如何使用?


Suspense 组件用于等待异步组件的加载结果。

<template>
  <Suspense>
    <template #default>
      <AsyncComponent />
    </template>
    <template #fallback>
      <p>Loading...</p>
    </template>
  </Suspense>
</template>

<script setup>
import { defineAsyncComponent } from 'vue'

const AsyncComponent = defineAsyncComponent(() => import('./AsyncComponent.vue'))
</script>

13. 如何在 Vue3 中使用 ref 和 reactive 的区别?

  • ref 适用于原始类型(如字符串、数字),它会返回一个对象,包含 value 属性。
  • reactive 适用于对象或数组,返回的是响应式对象。
import { ref, reactive } from 'vue'

const count = ref(0)
const state = reactive({ count: 0 })

// 可以直接修改

count.value++
state.count++


---

#### **14. Vue3 的 `v-bind` 和 `v-model` 区别?**

**答**:
- `v-bind` 用于绑定一个属性到某个组件。
- `v-model` 用于双向绑定,默认绑定 `value` 属性。

---

#### **15. Vue3 中如何实现状态管理?**

**答**:
Vue3 中的状态管理可以使用 **Pinia**,它是 Vue 官方推荐的状态管理库。

```javascript
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0
  }),
  actions: {
    increment() {
      this.count++
    }
  }
})

16. 如何在 Vue3 中使用 mixins?


Vue3 支持 mixins,虽然 Composition API 更推荐,但还是可以使用 mixins。

const myMixin = {
  data() {
    return {
      message: 'Hello'
    }
  },
  methods: {
    greet() {
      console.log(this.message)
    }
  }
}

17. Vue3 如何处理动态路由?


使用 Vue Router 来处理动态路由,使用 :param 来动态匹配 URL。

const routes = [
  {
    path: '/user/:id',
    component: User
  }
]

18. Vue3 中如何调试性能问题?


Vue3 提供了 Vue DevTools,可以用来分析组件性能,查看响应式数据流,以及查看生命周期。


19. Vue3 中如何使用 scoped slots?


Vue3 中使用 v-slot 来替代 scoped slots 语法。

<template #default="{ item }">
  <p>{{ item.name }}</p>
</template>

20. 如何在 Vue3 中优化性能?

  • 使用 keep-alive 缓存组件。
  • 使用异步组件和 Suspense
  • 避免不必要的 reactivity 和 watchers。

这些问题涵盖了 Vue3 中最常见的概念与技巧,能够帮助前端开发者在面试中充分展示自己的能力。