Vue3 基础教程
Vue3 是目前 Vue 生态的主流版本,基于 Composition API 重构,带来了更好的性能、更强的类型支持和更灵活的代码组织方式。本教程从环境搭建、核心语法到高级特性,全方位覆盖 Vue3 核心知识点,助你从入门到精通。
一、环境搭建
1. 前置条件
确保已安装 Node.js,可参考Nodejs基础教程(推荐 LTS 版本,v16+),验证方式:
bash
node -v # 输出版本号即安装成功
npm -v
2. 创建 Vue3 项目(Vite 脚手架)
Vite 是 Vue 官方推荐的构建工具,比 Webpack 更快,步骤如下:
bash
# 1. 创建项目(npm/yarn/pnpm 均可,推荐 npm)
npm create vite@latest my-vue3-project -- --template vue
# 2. 进入项目目录
cd my-vue3-project
# 3. 安装依赖
npm install
# 4. 启动开发服务器
npm run dev
启动后访问终端提示的地址(如 http://127.0.0.1:5173/),即可看到 Vue3 初始页面。
3. 项目目录结构解析
plaintext
my-vue3-project/
├── node_modules/ # 依赖包
├── public/ # 静态资源(不会被打包)
├── src/ # 核心源码目录
│ ├── assets/ # 静态资源(图片、样式,会被打包)
│ ├── components/ # 自定义组件
│ ├── App.vue # 根组件
│ └── main.js # 入口文件
├── .gitignore # git 忽略配置
├── index.html # 入口 HTML
├── package.json # 项目配置/依赖
└── vite.config.js # Vite 配置文件
二、Vue3 核心基础
1. 模板语法
Vue3 模板语法与 Vue2 基本一致,核心是「数据绑定」和「指令」。
(1)插值表达式
vue
<template>
<!-- 文本插值 -->
<div>{{ message }}</div>
<!-- 表达式插值(支持简单 JS 表达式) -->
<div>{{ count + 1 }}</div>
<div>{{ isShow ? '显示' : '隐藏' }}</div>
<!-- 原始 HTML(慎用,防止 XSS) -->
<div v-html="htmlContent"></div>
</template>
<script setup>
// Vue3 推荐 <script setup> 语法糖
const message = 'Hello Vue3!';
const count = 99;
const isShow = true;
const htmlContent = '<h1>Vue3 标题</h1>';
</script>
(2)指令
| 指令 | 作用 | 示例 |
|---|---|---|
v-bind |
绑定属性(简写 :) |
<img :src="imgUrl"> |
v-on |
绑定事件(简写 @) |
<button @click="handleClick"> |
v-model |
双向数据绑定 | <input v-model="username"> |
v-if/v-else |
条件渲染 | <div v-if="isLogin">已登录</div> |
v-for |
列表渲染 | <li v-for="item in list" :key="item.id">{{ item.name }}</li> |
v-show |
显示 / 隐藏(CSS 切换) | <div v-show="isShow">显示</div> |
示例:指令综合使用
vue
<template>
<!-- 条件渲染 -->
<div v-if="role === 'admin'">管理员</div>
<div v-else>普通用户</div>
<!-- 列表渲染 -->
<ul>
<li v-for="item in userList" :key="item.id">
{{ item.name }} - {{ item.age }}岁
</li>
</ul>
<!-- 双向绑定 + 事件绑定 -->
<input v-model="inputValue" placeholder="输入内容" />
<button @click="handleSubmit">提交</button>
<!-- 样式绑定 -->
<div :class="{ active: isActive }" :style="{ color: textColor }">样式绑定</div>
</template>
<script setup>
const role = 'admin';
const userList = [
{ id: 1, name: '张三', age: 20 },
{ id: 2, name: '李四', age: 22 }
];
const inputValue = '';
const handleSubmit = () => {
alert('提交内容:' + inputValue);
};
const isActive = true;
const textColor = 'red';
</script>
<style scoped>
.active {
font-weight: bold;
}
</style>
2. Composition API(组合式 API)
Vue3 核心升级点,替代 Vue2 的 Options API,解决「代码碎片化」问题,核心 API 如下:
(1)setup 语法糖(核心)
<script setup> 是 Vue3 推荐写法,无需手动导出,代码更简洁:
- 变量 / 函数直接在模板中使用
- 生命周期钩子前缀加
on(如onMounted) - 组件导入后直接使用
(2)响应式数据
Vue3 提供两种核心响应式 API:ref 和 reactive。
| API | 适用场景 | 访问方式 |
|---|---|---|
ref |
基本类型(String/Number) | .value(脚本中) |
reactive |
引用类型(Object/Array) | 直接访问属性 |
示例:响应式数据
vue
<template>
<div>
<p>计数(ref):{{ count }}</p>
<button @click="count++">+1</button>
<p>用户名(reactive):{{ user.name }}</p>
<button @click="updateName">修改名字</button>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue';
// 基本类型响应式
const count = ref(0);
// 引用类型响应式
const user = reactive({
name: '张三',
age: 20
});
// 修改 reactive 数据
const updateName = () => {
user.name = '李四';
};
</script>
(3)计算属性(computed)
基于响应式数据派生新值,缓存结果,依赖变化时自动更新:
vue
<template>
<div>
<p>原始价格:{{ price }}</p>
<p>折扣价格:{{ discountPrice }}</p>
<p>总价:{{ totalPrice }}</p>
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
const price = ref(100);
const count = ref(3);
// 只读计算属性
const discountPrice = computed(() => {
return price.value * 0.8;
});
// 可写计算属性
const totalPrice = computed({
get() {
return discountPrice.value * count.value;
},
set(newValue) {
price.value = newValue / count.value / 0.8;
}
});
// 测试可写
// totalPrice.value = 240; // 会触发 set,price 变为 100
</script>
(4)侦听器(watch /watchEffect)
监听响应式数据变化,执行副作用逻辑。
| API | 特点 |
|---|---|
watch |
显式指定监听源,可获取新旧值,惰性执行 |
watchEffect |
自动收集依赖,立即执行,无法获取旧值 |
示例:侦听器
vue
<template>
<div>
<input v-model="name" placeholder="输入名字" />
<input v-model="user.age" type="number" placeholder="输入年龄" />
</div>
</template>
<script setup>
import { ref, reactive, watch, watchEffect } from 'vue';
const name = ref('张三');
const user = reactive({ age: 20 });
// 监听 ref 数据
watch(name, (newVal, oldVal) => {
console.log('名字变化:', oldVal, '→', newVal);
});
// 监听 reactive 单个属性
watch(() => user.age, (newVal) => {
console.log('年龄变为:', newVal);
});
// 监听多个源
watch([name, () => user.age], ([newName, newAge]) => {
console.log('名字:', newName, '年龄:', newAge);
});
// watchEffect(自动收集依赖)
watchEffect(() => {
console.log('watchEffect:', name.value, user.age);
});
</script>
(5)生命周期钩子
Vue3 生命周期钩子需从 vue 导入,且在 <script setup> 中使用:
| Vue2 钩子 | Vue3 钩子(setup 中) | 触发时机 |
|---|---|---|
| beforeCreate | - | setup 中代码等效于此阶段 |
| created | - | setup 中代码等效于此阶段 |
| beforeMount | onBeforeMount | 组件挂载前 |
| mounted | onMounted | 组件挂载完成(DOM 可用) |
| beforeUpdate | onBeforeUpdate | 组件更新前 |
| updated | onUpdated | 组件更新完成 |
| beforeUnmount | onBeforeUnmount | 组件卸载前 |
| unmounted | onUnmounted | 组件卸载完成 |
示例:生命周期
vue
<template>
<div>生命周期示例</div>
</template>
<script setup>
import { onMounted, onUpdated, onUnmounted } from 'vue';
onMounted(() => {
console.log('组件挂载完成,可操作 DOM');
});
onUpdated(() => {
console.log('组件更新完成');
});
onUnmounted(() => {
console.log('组件卸载完成,清理定时器/事件');
});
</script>
3. 组件开发
Vue3 组件开发更灵活,支持全局组件和局部组件,核心是「Props 传值」和「事件派发」。
(1)组件定义与使用
步骤 1:创建子组件(src/components/Hello.vue)
vue
<template>
<div class="hello">
<h2>{{ title }}</h2>
<p>{{ content }}</p>
</div>
</template>
<script setup>
// 定义 Props
const props = defineProps({
title: {
type: String,
required: true, // 必填
default: '默认标题' // 默认值(非必填时生效)
},
content: {
type: String,
default: '默认内容'
}
});
</script>
<style scoped>
.hello {
padding: 20px;
border: 1px solid #eee;
}
</style>
步骤 2:在父组件中使用
vue
<template>
<div>
<!-- 传入 Props -->
<Hello title="Vue3 组件" content="组件通信示例" />
</div>
</template>
<script setup>
// 导入组件(自动局部注册)
import Hello from './components/Hello.vue';
</script>
(2)组件通信
| 通信方式 | 适用场景 | 实现方式 |
|---|---|---|
| Props | 父 → 子 | 子组件 defineProps 接收 |
| 自定义事件 | 子 → 父 | 子组件 emit,父组件 @监听 |
| provide/inject | 跨层级(爷 → 孙) | 父组件 provide,子组件 inject |
| Pinia/Vuex | 全局状态 | 全局仓库管理(下文详解) |
示例:自定义事件(子 → 父)
vue
<!-- 子组件(Child.vue) -->
<template>
<button @click="handleClick">向父组件传值</button>
</template>
<script setup>
// 定义可触发的事件
const emit = defineEmits(['sendData']);
const handleClick = () => {
// 触发事件并传参
emit('sendData', { id: 1, name: '子组件数据' });
};
</script>
<!-- 父组件 -->
<template>
<Child @sendData="receiveData" />
<p>子组件传来的数据:{{ childData.name }}</p>
</template>
<script setup>
import { ref } from 'vue';
import Child from './components/Child.vue';
const childData = ref({});
// 接收子组件数据
const receiveData = (data) => {
childData.value = data;
};
</script>
示例:provide/inject(跨层级)
vue
<!-- 父组件 -->
<template>
<Child />
</template>
<script setup>
import { provide } from 'vue';
import Child from './components/Child.vue';
// 提供数据
provide('theme', 'dark');
provide('userInfo', { name: '张三', age: 20 });
</script>
<!-- 孙组件(GrandChild.vue) -->
<template>
<div>
<p>主题:{{ theme }}</p>
<p>用户:{{ userInfo.name }}</p>
</div>
</template>
<script setup>
import { inject } from 'vue';
// 注入数据
const theme = inject('theme', 'light'); // 第二个参数是默认值
const userInfo = inject('userInfo');
</script>
4. 路由(Vue Router)
Vue Router 是 Vue 官方路由工具,用于实现单页应用(SPA)的页面跳转。
(1)安装
bash
npm install vue-router@4 # Vue3 对应 Router4 版本
(2)配置路由(src/router/index.js)
javascript
import { createRouter, createWebHistory } from 'vue-router';
// 导入页面组件
import Home from '../views/Home.vue';
import About from '../views/About.vue';
import User from '../views/User.vue';
// 路由规则
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: About
},
{
path: '/user/:id', // 动态路由
name: 'User',
component: User
}
];
// 创建路由实例
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL), // 历史模式
routes
});
export default router;
(3)在入口文件注册路由(src/main.js)
javascript
import { createApp } from 'vue';
import App from './App.vue';
import router from './router'; // 导入路由
const app = createApp(App);
app.use(router); // 注册路由
app.mount('#app');
(4)使用路由
vue
<!-- App.vue -->
<template>
<div>
<!-- 路由链接 -->
<router-link to="/">首页</router-link>
<router-link to="/about">关于</router-link>
<router-link to="/user/100">用户100</router-link>
<!-- 路由出口(匹配的组件渲染在这里) -->
<router-view />
</div>
</template>
<!-- User.vue(获取动态路由参数) -->
<template>
<div>用户ID:{{ $route.params.id }}</div>
</template>
<script setup>
// 也可通过组合式 API 获取路由
import { useRoute, useRouter } from 'vue-router';
const route = useRoute(); // 当前路由信息
const router = useRouter(); // 路由实例
// 编程式导航
const goHome = () => {
router.push('/');
};
console.log('用户ID:', route.params.id);
</script>
5. 状态管理(Pinia)
Pinia 是 Vue 官方推荐的状态管理工具,替代 Vuex,更简洁、支持 TypeScript,核心是「仓库(Store)」。
(1)安装
bash
npm install pinia
(2)创建 Pinia 实例(src/main.js)
javascript
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
const app = createApp(App);
app.use(createPinia()); // 注册 Pinia
app.mount('#app');
(3)创建仓库(src/stores/counter.js)
javascript
import { defineStore } from 'pinia';
// 定义仓库(第一个参数是仓库唯一标识)
export const useCounterStore = defineStore('counter', {
// 状态(类似 data)
state: () => ({
count: 0,
msg: 'Pinia 示例'
}),
// 计算属性(类似 computed)
getters: {
doubleCount: (state) => state.count * 2
},
// 方法(类似 methods,支持异步)
actions: {
increment() {
this.count++;
},
decrement() {
this.count--;
},
async asyncIncrement() {
await new Promise(resolve => setTimeout(resolve, 1000));
this.count++;
}
}
});
(4)使用仓库
vue
<template>
<div>
<p>计数:{{ counterStore.count }}</p>
<p>双倍计数:{{ counterStore.doubleCount }}</p>
<button @click="counterStore.increment">+1</button>
<button @click="counterStore.decrement">-1</button>
<button @click="counterStore.asyncIncrement">异步+1</button>
</div>
</template>
<script setup>
import { useCounterStore } from '../stores/counter';
// 获取仓库实例
const counterStore = useCounterStore();
// 也可解构(需用 storeToRefs 保持响应式)
// import { storeToRefs } from 'pinia';
// const { count, doubleCount } = storeToRefs(counterStore);
// const { increment } = counterStore;
</script>
三、Vue3 高级特性
1. 自定义指令
封装通用 DOM 操作,如自动聚焦、权限控制等。
(1)定义全局指令(src/main.js)
javascript
import { createApp } from 'vue';
import App from './App.vue';
const app = createApp(App);
// 自定义指令:v-focus(自动聚焦)
app.directive('focus', {
// 指令挂载到元素时触发
mounted(el) {
el.focus();
}
});
app.mount('#app');
(2)定义局部指令
vue
<template>
<input v-focus />
<div v-color="'red'">自定义颜色</div>
</template>
<script setup>
// 局部指令:v-color
const vColor = {
mounted(el, binding) {
el.style.color = binding.value;
}
};
</script>
2. 异步组件
按需加载组件,优化首屏加载速度。
vue
<template>
<AsyncComponent />
</template>
<script setup>
import { defineAsyncComponent } from 'vue';
// 定义异步组件
const AsyncComponent = defineAsyncComponent(() => {
return import('./components/AsyncComponent.vue');
});
</script>
3. Teleport(瞬移)
将组件 DOM 渲染到指定位置(如 body 下),解决层级嵌套问题(如弹窗、提示框)
vue
<template>
<button @click="showModal = true">打开弹窗</button>
<teleport to="body">
<div class="modal" v-if="showModal">
<div class="modal-content">
<h3>弹窗内容</h3>
<button @click="showModal = false">关闭</button>
</div>
</div>
</teleport>
</template>
<script setup>
import { ref } from 'vue';
const showModal = ref(false);
</script>
<style scoped>
.modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.5);
display: flex;
justify-content: center;
align-items: center;
}
.modal-content {
background: white;
padding: 20px;
border-radius: 4px;
}
</style>
4. Suspense(悬念)
等待异步组件加载完成前显示占位内容,提升用户体验。
vue
<template>
<Suspense>
<!-- 异步组件 -->
<template #default>
<AsyncComponent />
</template>
<!-- 加载中占位 -->
<template #fallback>
<div>加载中...</div>
</template>
</Suspense>
</template>
<script setup>
import { defineAsyncComponent } from 'vue';
const AsyncComponent = defineAsyncComponent(() => {
return new Promise(resolve => {
setTimeout(() => {
resolve(import('./components/AsyncComponent.vue'));
}, 2000);
});
});
</script>
四、项目优化与部署
1. 性能优化
- 路由懒加载:异步组件 + 路由拆分,减少首屏体积
- 图片优化 :使用
vite-plugin-imagemin压缩图片,懒加载图片 - 组件缓存 :使用
keep-alive缓存频繁切换的组件 - 减少重渲染 :合理使用
computed、shallowRef/shallowReactive减少响应式开销
2. 打包构建
bash
# 生产环境打包
npm run build
打包后的文件在 dist 目录,可直接部署到静态服务器(如 Nginx、Netlify、Vercel)。
3. 部署示例(Nginx)
nginx
server {
listen 80;
server_name your-domain.com;
root /path/to/dist; # 打包后的 dist 目录路径
index index.html;
# 解决路由刷新 404 问题
location / {
try_files $uri $uri/ /index.html;
}
}
五、学习资源与进阶方向
1. 官方资源
- Vue3 官方文档:cn.vuejs.org/guide/intro...
- Vue Router 文档:router.vuejs.org/zh/
- Pinia 文档:pinia.vuejs.org/zh/
- Vite 文档:vitejs.dev/guide/
2. 进阶方向
- TypeScript 集成:Vue3 + TS 提升代码可维护性
- 组件库开发:基于 Vue3 开发自定义组件库(如 Element Plus)
- SSR 服务端渲染:Nuxt3(Vue3 生态的 SSR 框架)
- 跨端开发:UniApp/Taro 基于 Vue3 开发多端应用(小程序 / APP/H5)
- 状态管理进阶:Pinia 持久化、模块化设计
总结
Vue3 的核心是 Composition API,相比 Vue2 更灵活、更易维护。本教程覆盖了 Vue3 从环境搭建到高级特性的全量知识点,建议结合实战项目(如个人博客、电商后台)巩固学习。掌握基础后,可深入学习 TypeScript 集成、性能优化等进阶内容,成为 Vue3 资深开发者。