关于vue3
前言
Vue3 作为目前最流行的前端框架之一,带来了许多激动人心的新特性和改进。无论是性能优化、开发体验还是代码组织方式,Vue3 都有了质的飞跃。本博客将带你从零开始,首先学习如何搭建 Vue 3 项目,然后逐步深入其核心特性,并通过一个实战项目,让你掌握 Vue3 的开发技巧。
第一章:搭建你的第一个 Vue 3 项目
在开始学习 Vue3 的核心特性之前,我们首先需要一个可以运行的项目环境。目前,官方最推荐的方式是使用 Vite 来创建 Vue3 项目,因为它能提供极速的开发体验。
前提条件
确保你的电脑上已经安装了 Node.js (推荐版本为 18.0 或更高)。你可以在终端中运行以下命令来检查 Node.js 是否安装成功:
node -v
# v18.17.1 # 看到类似这样的版本号即表示安装成功
步骤 1: 使用 Vite 创建项目
打开你的终端(在 Windows 上可以使用 CMD 或 PowerShell,在 macOS/Linux 上使用 Terminal),然后运行以下命令:
# npm 方式 (推荐)
npm create vite@latest# yarn 方式 (如果你习惯使用 yarn)
# yarn create vite# pnpm 方式 (如果你习惯使用 pnpm)
# pnpm create vite
步骤 2: 配置项目信息
运行命令后,Vite 会引导你进行项目配置:
- 项目名称: 输入你的项目名称,例如
vue3-todo-app。 - 选择框架: 上下箭头键选择
Vue,然后按回车。 - 选择变体: 再次使用上下箭头键,根据你的喜好选择
JavaScript或TypeScript。对于本教程,选择JavaScript即可。
配置过程如下所示:
√ Project name: ... vue3-todo-app
√ Select a framework: » Vue
√ Select a variant: » JavaScriptScaffolding project in /path/to/your/project/vue3-todo-app...Done. Now run:cd vue3-todo-appnpm installnpm run dev
步骤 3: 进入项目并安装依赖
根据终端的提示,执行以下命令:
# 进入你刚刚创建的项目目录
cd vue3-todo-app# 安装项目所需的依赖包
npm install
步骤 4: 启动开发服务器
依赖安装完成后,运行以下命令来启动本地开发服务器:
npm run dev
启动成功后,你会在终端看到类似下面的信息,告诉你项目运行在哪个地址上:
VITE v4.4.9 ready in 300 ms➜ Local: http://127.0.0.1:5173/➜ Network: use --host to expose
现在,打开你的浏览器,访问 http://127.0.0.1:5173/,你应该能看到 Vue3 的欢迎页面,这表示你的项目已经成功创建并运行起来了!
项目目录结构
让我们简单了解一下 Vite 创建的 Vue3 项目结构:
vue3-todo-app/
├── node_modules/ # 项目依赖
├── public/ # 静态资源文件夹
├── src/ # 源代码文件夹 (我们主要在这里工作)
│ ├── assets/ # 图片、字体等资源
│ ├── components/ # Vue 组件文件夹
│ │ └── HelloWorld.vue # 一个示例组件
│ ├── App.vue # 根组件
│ ├── main.js # 入口文件,用于创建 Vue 应用
│ └── style.css # 全局样式文件
├── .gitignore # Git 忽略文件配置
├── index.html # 应用的 HTML 入口
├── package.json # 项目配置和依赖管理
└── vite.config.js # Vite 的配置文件
第二章:为什么选择 Vue3?
Vue3 相比 Vue2 有以下几个显著的优势:
- 更好的性能:Vue3 使用了 Proxy 代替 Object.defineProperty 实现响应式,性能更高,并且支持对数组、Map、Set 等数据结构的响应式处理。
- 更小的体积:通过 Tree-shaking 优化,Vue3 的核心库体积更小,只引入需要的功能。
- Composition API:提供了全新的 Composition API,让代码组织更加灵活,更适合大型项目。
- TypeScript 支持:Vue3 完全用 TypeScript 重写,提供了更好的类型推断和类型检查。
- 更好的扩展性:支持自定义渲染器,可以将 Vue 组件渲染到不同的平台。
第三章:Vue3 核心特性
1. Composition API
Composition API 是 Vue3 最重要的新特性之一。它允许我们将组件的逻辑按照功能进行组织,而不是按照选项(data、methods、computed 等)进行分割。
示例代码:
<template><div><p>Count: {{ count }}</p><button @click="increment">Increment</button></div>
</template><script setup>
import { ref, onMounted } from 'vue';// 响应式数据
const count = ref(0);// 方法
const increment = () => {count.value++;
};// 生命周期钩子
onMounted(() => {console.log('Component mounted');
});
</script>
2. 响应式系统
Vue3 的响应式系统基于 Proxy 实现,相比 Vue2 的 Object.defineProperty 有以下改进:
- 支持对数组索引和 length 属性的响应式处理
- 支持对 Map、Set、WeakMap、WeakSet 的响应式处理
- 不需要手动处理数组的变异方法(push、pop、shift、unshift 等)
示例代码:
import { reactive, watch } from 'vue';const state = reactive({name: 'Vue3',age: 3,hobbies: ['reading', 'coding']
});// 监听响应式数据变化
watch(() => state.name, (newVal, oldVal) => {console.log(`Name changed from ${oldVal} to ${newVal}`);
});state.name = 'Vue'; // 触发 watch
state.hobbies.push('running'); // 触发 watch
3. 生命周期钩子
Vue3 的生命周期钩子相比 Vue2 有一些变化,并且可以在 Composition API 中使用。
常用生命周期钩子:
onBeforeMount:组件挂载前调用onMounted:组件挂载后调用onBeforeUpdate:组件更新前调用onUpdated:组件更新后调用onBeforeUnmount:组件卸载前调用onUnmounted:组件卸载后调用
示例代码:
<script setup>
import { onMounted, onUnmounted } from 'vue';onMounted(() => {console.log('Component mounted');
});onUnmounted(() => {console.log('Component unmounted');
});
</script>
4. 模板语法改进
Vue3 的模板语法相比 Vue2 有一些改进,包括:
- 支持多个根节点
- 支持片段(Fragment)
- 支持 Teleport 组件,可以将组件的内容渲染到 DOM 树的其他位置
- 支持 Suspense 组件,可以处理异步组件的加载状态
示例代码:
<template><div>Root node 1</div><div>Root node 2</div>
</template>
第四章:实战项目:Todo List
接下来,我们将通过一个简单的 Todo List 项目,来实践 Vue3 的核心特性。
编写 Todo List 组件
在 src/components 目录下创建 TodoList.vue 文件,并填入以下代码:
<template><div class="todo-list"><h1>Todo List</h1><!-- 添加 todo --><div class="add-todo"><input type="text" v-model="newTodo" placeholder="Add a new todo..."@keyup.enter="addTodo"><button @click="addTodo">Add</button></div><!-- 过滤 todo --><div class="filters"><button :class="{ active: filter === 'all' }"@click="setFilter('all')">All</button><button :class="{ active: filter === 'active' }"@click="setFilter('active')">Active</button><button :class="{ active: filter === 'completed' }"@click="setFilter('completed')">Completed</button></div><!-- 显示 todo 列表 --><ul class="todo-items"><li v-for="todo in filteredTodos" :key="todo.id":class="{ completed: todo.completed }"><input type="checkbox" v-model="todo.completed"><span>{{ todo.text }}</span><button @click="deleteTodo(todo.id)">×</button></li></ul><!-- 清除已完成 todo --><div class="clear-completed"><button @click="clearCompleted":disabled="!hasCompletedTodos">Clear completed</button></div></div>
</template><script setup>
import { ref, computed } from 'vue';// 响应式数据
const todos = ref([{ id: 1, text: 'Learn Vue3', completed: false },{ id: 2, text: 'Build a todo app', completed: false }
]);
const newTodo = ref('');
const filter = ref('all');// 计算属性:过滤 todo
const filteredTodos = computed(() => {switch (filter.value) {case 'active':return todos.value.filter(todo => !todo.completed);case 'completed':return todos.value.filter(todo => todo.completed);default:return todos.value;}
});// 计算属性:是否有已完成的 todo
const hasCompletedTodos = computed(() => {return todos.value.some(todo => todo.completed);
});// 方法:添加 todo
const addTodo = () => {if (newTodo.value.trim() !== '') {todos.value.push({id: Date.now(),text: newTodo.value.trim(),completed: false});newTodo.value = '';}
};// 方法:删除 todo
const deleteTodo = (id) => {todos.value = todos.value.filter(todo => todo.id !== id);
};// 方法:设置过滤条件
const setFilter = (value) => {filter.value = value;
};// 方法:清除已完成 todo
const clearCompleted = () => {todos.value = todos.value.filter(todo => !todo.completed);
};
</script><style scoped>
/* 样式部分保持不变 */
.todo-list {max-width: 600px;margin: 2rem auto;padding: 20px;font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;border: 1px solid #e0e0e0;border-radius: 8px;box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}
/* ... (省略其余样式以保持简洁,实际使用时请保留完整样式) ... */
</style>
在 App.vue 中使用 TodoList 组件
修改 src/App.vue 文件,使其内容如下:
<template><div id="app"><TodoList /></div>
</template><script setup>
import TodoList from './components/TodoList.vue';
</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>
第五章:Vue3 生态系统
Vue3 拥有丰富的生态系统,包括:
- Vue Router:官方路由库,用于构建单页应用。
- Pinia:官方状态管理库,替代了 Vuex。
- Vue Test Utils:官方测试工具库,用于测试 Vue 组件。
- Vue Devtools:浏览器开发者工具,用于调试 Vue 应用。
使用 Pinia 进行状态管理
Pinia 是 Vue3 推荐的状态管理库,相比 Vuex 有以下改进:
- 更简单的 API
- 更好的 TypeScript 支持
- 不需要嵌套模块
- 支持组合式 API
示例代码:
- 安装 Pinia:
npm install pinia - 在
main.js中引入 Pinia:import { createApp } from 'vue' import { createPinia } from 'pinia' import App from './App.vue'createApp(App).use(createPinia()).mount('#app') - 创建 store:
// src/stores/todo.js import { defineStore } from 'pinia'export const useTodoStore = defineStore('todo', {state: () => ({todos: [{ id: 1, text: 'Learn Vue3', completed: false },{ id: 2, text: 'Build a todo app', completed: false }]}),getters: {activeTodos: (state) => state.todos.filter(todo => !todo.completed),completedTodos: (state) => state.todos.filter(todo => todo.completed)},actions: {addTodo(text) {this.todos.push({id: Date.now(),text,completed: false})},deleteTodo(id) {this.todos = this.todos.filter(todo => todo.id !== id)},toggleTodo(id) {const todo = this.todos.find(todo => todo.id === id)if (todo) {todo.completed = !todo.completed}}} }) - 在组件中使用 store:
<script setup> import { useTodoStore } from '@/stores/todo'const todoStore = useTodoStore()// 访问 state console.log(todoStore.todos)// 访问 getters console.log(todoStore.activeTodos)// 调用 actions todoStore.addTodo('Learn Pinia') </script>
