Vue3作为Vue.js的最新版本,带来了更小的体积、更快的渲染速度以及Composition API等新特性,使得开发更加灵活高效。本文将详细介绍Vue3的核心概念、组件通信方式以及面试中常见的真题,并提供实战项目指导,帮助开发者更好地掌握Vue3在大厂面试中的应用。
Vue3 是 Vue.js 的最新版本,相比 Vue2,它带来了许多重要的改进和新特性。以下是 Vue3 的核心特性:
更小的体积和更快的渲染:
更好的类型支持:
Composition API:
Teleport 与 Fragments:
更好的错误处理和调试信息:
// 使用 Composition API 创建组件 import { defineComponent } from 'vue'; const MyComponent = defineComponent({ setup() { const message = 'Hello Vue3'; return { message }; }, template: '<div>{{ message }}</div>' }); export default MyComponent;
在从 Vue2 迁移到 Vue3 时,可能会遇到一些常见的问题和挑战。以下是一些常见问题及解决方案:
生命周期钩子的变化:
beforeDestroy
和 destroyed
钩子,取而代之的是 beforeUnmount
和 unmounted
,分别用于替代 beforeDestroy
和 destroyed
。beforeDestroy
和 destroyed
替换为 beforeUnmount
和 unmounted
。选项式 API 和 Composition API 的使用:
响应式系统的变化:
Component 的参数变化:
Vue.component
方法已被 defineComponent
代替。defineComponent
来定义组件。// Vue2 示例 Vue.component('my-component', { data() { return { message: 'Hello Vue2' }; }, template: '<div>{{ message }}</div>' }); // Vue3 示例 import { defineComponent } from 'vue'; const MyComponent = defineComponent({ data() { return { message: 'Hello Vue3' }; }, template: '<div>{{ message }}</div>' });
下面是一个从 Vue2 到 Vue3 的典型迁移示例:
// Vue2 示例 Vue.component('app', { data() { return { message: 'Hello Vue2' }; }, beforeDestroy() { console.log('Component is about to be destroyed.'); }, template: '<div>{{ message }}</div>' }); // Vue3 示例 import { defineComponent, onBeforeUnmount, ref } from 'vue'; import { createApp } from 'vue'; const App = defineComponent({ setup() { const message = ref('Hello Vue3'); onBeforeUnmount(() => { console.log('Component is about to be unmounted.'); }); return { message } }, template: '<div>{{ message }}</div>' }); createApp(App).mount('#app');
Vue 组件之间的通信是开发中常见的需求。Vue3 支持多种组件通信的方法,包括 props、事件、提供/使用(provide/inject)、状态管理库等。下面详细解释每种方式:
Props:
// 父组件 <template> <child-component :message="parentMessage" /> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { components: { ChildComponent }, data() { return { parentMessage: 'Hello from parent' }; } }; </script> // 子组件 <template> <div>{{ message }}</div> </template> <script> export default { props: ['message'] }; </script>
事件:
$emit
方法触发事件,父组件通过 v-on
监听事件。// 子组件 <template> <button @click="sendMessage">Send Message</button> </template> <script> export default { methods: { sendMessage() { this.$emit('messageEvent', 'Hello from child'); } } }; </script> // 父组件 <template> <child-component @messageEvent="handleMessage" /> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { components: { ChildComponent }, methods: { handleMessage(message) { console.log(message); // 输出: Hello from child } } }; </script>
provide/inject:
// 爷组件 <script> import { provide, ref } from 'vue'; import ChildComponent from './ChildComponent.vue'; export default { components: { ChildComponent }, setup() { const message = ref('Hello from grandparent'); provide('message', message); return { message } } }; </script> // 子组件 <script> import { inject } from 'vue'; export default { setup() { const message = inject('message'); return { message } }, template: '<div>{{ message }}</div>' }; </script>
状态管理库:
// Vuex Store import { createStore } from 'vuex'; export default createStore({ state: { message: 'Hello from store' }, mutations: { updateMessage(state, newMessage) { state.message = newMessage; } } }); // 父组件 <script> import { useStore } from 'vuex'; export default { setup() { const store = useStore(); store.commit('updateMessage', 'Hello from parent'); return { message: computed(() => store.state.message) } }, template: '<div>{{ message }}</div>' }; </script>
Composition API 是 Vue3 引入的一个新特性,它允许开发者通过 setup
函数来组织和组合组件逻辑。Composition API 主要有以下几个核心概念:
setup 函数:
setup
函数是 Composition API 的入口点,用于定义组件的逻辑。import { ref, onMounted } from 'vue'; export default { setup() { const count = ref(0); onMounted(() => { console.log('Component is mounted'); }); return { count } } };
ref 和 reactive:
ref
用于简单类型的数据,如数字或字符串。reactive
用于复杂类型的数据,如对象或数组。import { ref, reactive } from 'vue'; export default { setup() { const count = ref(0); const user = reactive({ name: 'John Doe', age: 30 }); return { count, user } } };
生命周期钩子:
onMounted
、onUnmounted
、onBeforeUnmount
等钩子来替代 Vue2 中的生命周期方法。import { onMounted, onUnmounted } from 'vue'; export default { setup() { onMounted(() => { console.log('Component is mounted'); }); onUnmounted(() => { console.log('Component is unmounted'); }); return {}; } };
computed 和 watch:
computed
用于定义计算属性。watch
用于监听数据的变化。import { ref, computed, watch } from 'vue'; export default { setup() { const count = ref(0); const doubleCount = computed(() => count.value * 2); watch(count, (newVal, oldVal) => { console.log('count changed from', oldVal, 'to', newVal); }); return { count, doubleCount } } };
Vue3 使用了全新的响应式系统,基于 Proxy 而非 Vue2 中的 Object.defineProperty。以下是 Vue3 响应式原理的一些关键点:
Proxy:
Dep 依赖收集:
Watcher 观察者:
Reactive 创建响应式对象:
reactive
函数用于创建一个响应式对象。reactive
创建的对象,其属性的读取和修改都会触发响应式更新。import { reactive } from 'vue'; const state = reactive({ count: 0 }); console.log(state.count); // 0 state.count++; console.log(state.count); // 1
Ref 创建响应式引用:
ref
函数用于创建一个响应式引用。ref
创建的引用,其 value
属性的读取和修改都会触发响应式更新。import { ref } from 'vue'; const count = ref(0); console.log(count.value); // 0 count.value++; console.log(count.value); // 1
Reactivity Transform:
ReactivityTransform
功能,可以自动将普通对象转换为响应式对象。<template> <div>{{ obj.count }}</div> </template> <script> import { reactive } from 'vue'; const obj = reactive({ count: 0 }); obj.count++; console.log(obj.count); // 1 </script>
选择题
ref
用于创建什么类型的响应式数据?
setup
函数接收两个参数,分别是 props
和 context
,其中 context
包含了 attrs
、slots
和 __。emit
问题:实现一个简单的计数器组件,可以点击按钮递增和递减计数器的值。
<template> <div> <p>{{ count }}</p> <button @click="increment">Increment</button> <button @click="decrement">Decrement</button> </div> </template> <script> import { ref, reactive } from 'vue'; export default { setup() { const count = ref(0); const increment = () => { count.value++; }; const decrement = () => { count.value--; }; return { count, increment, decrement }; } }; </script>
问题:实现一个父组件传递数据给子组件,并在子组件中修改数据后,父组件也能接收到更新后的数据。
<!-- 父组件 --> <template> <div> <p>{{ message }}</p> <child-component :message="message" @updateMessage="updateMessage" /> </div> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { components: { ChildComponent }, data() { return { message: 'Hello from parent' }; }, methods: { updateMessage(newMessage) { this.message = newMessage; } } }; </script> <!-- 子组件 --> <template> <div> <p>{{ message }}</p> <button @click="sendMessage">Send Message</button> </div> </template> <script> import { ref, onMounted } from 'vue'; export default { props: ['message'], setup(props, { emit }) { const message = ref(props.message); const sendMessage = () => { message.value = 'Hello from child'; emit('updateMessage', message.value); }; return { message, sendMessage }; } }; </script>
要创建并管理 Vue3 项目,你可以使用 Vue CLI。下面是一个详细的步骤:
安装 Vue CLI:
npm install -g @vue/cli
创建 Vue3 项目:
vue create my-vue3-project
配置项目:
src/main.js
、src/App.vue
等文件的内容。// src/main.js import { createApp } from 'vue'; import App from './App.vue'; createApp(App).mount('#app');
<!-- src/App.vue --> <template> <div id="app"> <h1>Hello Vue3</h1> </div> </template> <script> export default { name: 'App' }; </script> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
运行项目:
npm run serve
创建新项目:
vue create my-vue3-project
初始化项目:
cd my-vue3-project npm install
配置项目:
npm install vue-router vuex
// src/router/index.js import { createRouter, createWebHistory } from 'vue-router'; import Home from '../views/Home.vue'; const routes = [ { path: '/', component: Home } ]; const router = createRouter({ history: createWebHistory(), routes }); export default router;
// src/store/index.js import { createStore } from 'vuex'; export default createStore({ state: { message: 'Hello from store' }, mutations: { updateMessage(state, newMessage) { state.message = newMessage; } } });
开发项目:
npm run serve
技术准备:
项目经验:
清晰表达:
代码展示:
善于提问:
体现团队合作:
问题:Vue3 在实际项目中的应用案例有哪些?
代码示例:
<template> <div> <h1>Login</h1> <input type="text" v-model="username" placeholder="Username" /> <input type="password" v-model="password" placeholder="Password" /> <button @click="login">Login</button> </div> </template> <script> import { ref, reactive } from 'vue'; import { useStore } from 'vuex'; export default { setup() { const username = ref(''); const password = ref(''); const store = useStore(); const login = () => { store.dispatch('login', { username: username.value, password: password.value }); }; return { username, password, login }; } }; </script>
问题:个人项目与 Vue3 的结合点有哪些?
代码示例:
<template> <div> <h1>Blog Posts</h1> <div v-for="post in posts" :key="post.id"> <h2>{{ post.title }}</h2> <p>{{ post.content }}</p> </div> </div> </template> <script> import { ref, onMounted } from 'vue'; import axios from 'axios'; export default { setup() { const posts = ref([]); onMounted(() => { axios.get('/api/posts') .then(response => { posts.value = response.data; }); }); return { posts }; } }; </script>
ref
创建了一个文章列表的响应式引用,并在组件挂载时通过 Axios 获取文章数据。