本文提供了Vue3的全面入门教程,涵盖了Vue3的基本概念、新特性、项目搭建、组件化开发、路由与状态管理以及生命周期方法等内容。通过一个简单的待办事项列表应用,进一步展示了Vue3的实际应用。希望这些内容能够帮助开发者快速上手Vue3,构建高效的前端应用。
Vue.js 是一个渐进式 JavaScript 框架,它于 2014 年由尤雨溪(Evan You)开发,主要用于构建用户界面。Vue.js 采用了 MVVM(Model-View-ViewModel)的设计模式,提供了一种将 DOM 和数据绑定在一起的方法,使得开发者能够更高效地构建交互式前端应用。Vue.js 的设计目标是尽可能地保持轻量级,同时提供强大的功能。它既适合新手快速上手,也非常适合开发者构建复杂的单页应用(SPA)。
Vue3 提供了许多新特性,使开发体验更加高效和灵活。这些新特性包括:
Composition API: 组件逻辑的组合能力更强,使用 setup()
函数可替代选项式 API,提供更灵活的逻辑组合和复用。
<script setup> import { ref } from 'vue' const count = ref(0) </script>
Teleport 和 Suspense: 新增的 Teleport
组件可以将子组件渲染到 DOM 的任何位置,而 Suspense
则可以优化异步组件的渲染过程。
<teleport to="#teleport-target"> <div>Teleported Content</div> </teleport> <Suspense> <template #default> <div>Loading...</div> </template> <template #fallback> <div>Loading...</div> </template> </Suspense>
Deprecation of Options API: 部分旧的选项式 API 用法将逐渐被废弃,如 data
、computed
和 methods
等属性,未来推荐使用 Composition API。
TypeScript 支持: Vue 3 完全支持 TypeScript,并改进了类型推断和接口定义。
<script lang="ts"> import { defineComponent, ref } from 'vue' export default defineComponent({ setup() { const message = ref('Hello TypeScript in Vue 3') return { message } } }) </script>
性能提升: Vue 3 重构了响应式系统,使得数据绑定和组件渲染更为高效。
这些新特性使得 Vue3 成为了构建现代前端应用的理想工具。
要开始使用 Vue3 开发项目,首先需要安装 Vue CLI(命令行工具)。Vue CLI 是一个快速开发 Vue 项目的工具,提供了许多命令来简化项目创建和配置过程。
全局安装 Vue CLI:
npm install -g @vue/cli
安装完成后,通过 Vue CLI 创建项目:
vue create my-vue3-project
创建项目时,可以选用默认的预设模板,或自定义配置。
选择 Vue 3 版本:
在创建项目过程中,选择 Vue 3 作为基础模板。选择适当的预设选项来定制你的项目结构。
cd my-vue3-project npm run serve
这将启动一个开发服务器,可以在浏览器中访问 http://localhost:8080
来查看你的 Vue3 项目。
要创建一个 Vue3 项目,可以使用 Vue CLI 提供的命令行工具来初始化项目。以下是创建一个简单的 Vue3 项目的步骤:
安装 Vue CLI (如果尚未安装):
npm install -g @vue/cli
创建一个新的 Vue 3 项目:
vue create my-vue3-project
选择预设模板:
在创建项目过程中,选择 Manually select features
,然后选择 Vue 3 版本。这将允许你选择所需的特性,如 Babel、Router、Vuex、Lint 等。
cd my-vue3-project npm run serve
接下来,您可以使用开发服务器,访问 http://localhost:8080
来查看正在运行的 Vue3 项目。
# 全局安装 Vue CLI npm install -g @vue/cli # 创建 Vue 项目 vue create my-vue3-project # 进入项目目录 cd my-vue3-project # 启动开发服务器 npm run serve
组件是 Vue 中构建可复用 UI 的基石。每个组件通常由一个 HTML 模板、一个 JavaScript 文件和一个 CSS 文件组成。在 Vue 3 中,组件可以被定义为独立的文件,也可以在一个文件中同时定义模板、脚本和样式。
一个简单的 Vue 组件可以按如下结构定义:
<!-- HelloWorld.vue --> <template> <div> <h1>{{ message }}</h1> </div> </template> <script> export default { name: 'HelloWorld', data() { return { message: 'Hello Vue 3' } } } </script> <style scoped> h1 { color: #42b983; } </style>
在上面的代码中,组件名称为 HelloWorld
,它有一个 message
数据属性,该属性在模板中使用双花括号语法 {{ message }}
括起来进行绑定。
组件可以在其他 Vue 文件中通过 <script>
标签引入并使用:
<!-- App.vue --> <template> <div id="app"> <HelloWorld /> </div> </template> <script> import HelloWorld from './components/HelloWorld.vue' export default { name: 'App', components: { HelloWorld } } </script>
数据绑定是 Vue 中的关键特性之一,它允许在组件的数据属性和 DOM 元素之间进行高效的动态交互。事件处理则使我们能够响应用户输入,如点击按钮或输入文本。
数据绑定可以通过 v-bind
指令实现,也可以使用简写的 :
语法:
<template> <div> <p>{{ message }}</p> <p>{{ name }}</p> </div> </template> <script> export default { name: 'DataBindingExample', data() { return { message: 'Hello Vue 3', name: 'World' } } } </script>
此外,还可以绑定属性:
<template> <div> <img v-bind:class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="imageSrc" /> </div> </template> <script> export default { name: 'DataBindingExample', data() { return { imageSrc: 'https://vuejs.org/images/logo.png' } } } </script>
事件处理通常使用 v-on
指令,也可以简写为 @
:
<template> <div> <button @click="onClick">Click Me!</button> </div> </template> <script> export default { name: 'EventHandlingExample', methods: { onClick() { alert('Button Clicked'); } } } </script>
<!-- Button.vue --> <template> <div> <button @click="handleClick">Click Me!</button> </div> </template> <script> export default { name: 'Button', methods: { handleClick() { alert('Button clicked'); } } } </script> <style scoped> button { background-color: #42b983; color: white; padding: 10px 20px; border: none; border-radius: 5px; } </style>
<!-- App.vue --> <template> <div id="app"> <Button /> </div> </template> <script> import Button from './components/Button.vue'; export default { name: 'App', components: { Button } } </script>
Vue Router 是 Vue.js 官方推荐的路由库,用于实现单页面应用中的路由切换。Vue Router 通过定义路由规则来管理不同的视图组件,使得用户在不同的页面之间导航。
首先安装 Vue Router:
npm install vue-router@next --save
创建一个 router.js
文件,配置路由规则:
// router.js import { createRouter, createWebHistory } from 'vue-router' import Home from './views/Home.vue' import About from './views/About.vue' const routes = [ { path: '/', component: Home }, { path: '/about', component: About } ] const router = createRouter({ history: createWebHistory(), routes }) export default router
然后在 main.js
中引入并使用路由配置:
// main.js import { createApp } from 'vue' import App from './App.vue' import router from './router' createApp(App).use(router).mount('#app')
在组件中使用 router-link
标签进行导航,或者直接通过编程方式触发:
<!-- Navigation.vue --> <template> <div> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> </div> </template>
Vuex 是一个专为 Vue.js 应用程序设计的状态管理模式,它通过一个集中的状态树来管理应用的所有组件的状态。Vuex 提供了一种可预测的状态管理方式,使得组件之间的状态管理更加集中和高效。
首先安装 Vuex:
npm install vuex@next --save
创建一个 store.js
文件,配置 Vuex store:
// store.js import { createStore } from 'vuex' export default createStore({ state: { count: 0 }, mutations: { increment(state) { state.count++ } }, actions: { increment({ commit }) { commit('increment') } }, getters: { count: state => state.count } })
然后在 main.js
中引入并使用 Vuex store:
// main.js import { createApp } from 'vue' import App from './App.vue' import router from './router' import store from './store' createApp(App).use(router).use(store).mount('#app')
在组件中通过 mapState
和 mapActions
来访问 Vuex store 中的状态和方法:
<!-- Counter.vue --> <template> <div> <p>{{ count }}</p> <button @click="increment">Increment</button> </div> </template> <script> import { mapState, mapActions } from 'vuex' export default { name: 'Counter', computed: { ...mapState(['count']) }, methods: { ...mapActions(['increment']) } } </script>
// router.js import { createRouter, createWebHistory } from 'vue-router' import Home from './views/Home.vue' import About from './views/About.vue' const routes = [ { path: '/', component: Home }, { path: '/about', component: About } ] const router = createRouter({ history: createWebHistory(), routes }) export default router
// store.js import { createStore } from 'vuex' export default createStore({ state: { count: 0 }, mutations: { increment(state) { state.count++ } }, actions: { increment({ commit }) { commit('increment') } }, getters: { count: state => state.count } })
<!-- Counter.vue --> <template> <div> <p>{{ count }}</p> <button @click="increment">Increment</button> </div> </template> <script> import { mapState, mapActions } from 'vuex' export default { name: 'Counter', computed: { ...mapState(['count']) }, methods: { ...mapActions(['increment']) } } </script>
Vue 组件的生命周期包括多个阶段,每个阶段都有相应的钩子函数,使得开发者能够更灵活地控制组件的行为。这些钩子函数可以用来执行一些特定的操作,如初始化状态、异步请求数据等。
生命周期钩子提供了丰富的回调方法,使得开发者能够更精确地控制组件的生命周期。这些方法可以在钩子函数中使用,用以定义组件在特定阶段应该执行的操作。
<!-- LifeCycleHooks.vue --> <template> <div> <h1>{{ message }}</h1> <button @click="changeMessage">Change Message</button> </div> </template> <script> export default { name: 'LifeCycleHooks', data() { return { message: 'LifeCycle Hooks' } }, beforeCreate() { console.log('beforeCreate'); }, created() { console.log('created'); }, beforeMount() { console.log('beforeMount'); }, mounted() { console.log('mounted'); }, beforeUpdate() { console.log('beforeUpdate'); }, updated() { console.log('updated'); }, beforeUnmount() { console.log('beforeUnmount'); }, unmounted() { console.log('unmounted'); }, methods: { changeMessage() { this.message = 'Message Changed' } } } </script>
<!-- LifeCycleHooks.vue --> <template> <div> <h1>{{ message }}</h1> <button @click="changeMessage">Change Message</button> </div> </template> <script> export default { name: 'LifeCycleHooks', data() { return { message: 'LifeCycle Hooks' } }, beforeCreate() { console.log('beforeCreate'); }, created() { console.log('created'); }, beforeMount() { console.log('beforeMount'); }, mounted() { console.log('mounted'); }, beforeUpdate() { console.log('beforeUpdate'); }, updated() { console.log('updated'); }, beforeUnmount() { console.log('beforeUnmount'); }, unmounted() { console.log('unmounted'); }, methods: { changeMessage() { this.message = 'Message Changed' } } } </script>
本节将通过一个简单的 Vue3 项目来展示如何在实际开发中使用 Vue3 的各项功能。我们将构建一个简单的待办事项列表应用,该应用将具备以下功能:
这个项目将使用 Vue3 的基础组件、路由和状态管理(Vuex)功能。
首先,我们使用 vue create
命令创建一个新的 Vue3 项目:
vue create my-todo-app cd my-todo-app
然后,安装必要的依赖库:
npm install vue-router vuex
项目的基本结构如下:
my-todo-app/ ├── public/ ├── src/ │ ├── assets/ │ ├── components/ │ ├── views/ │ ├── App.vue │ ├── main.js │ ├── router.js │ ├── store.js │ └── index.html ├── package.json ├── babel.config.js └── vue.config.js
在 router.js
文件中配置路由信息:
// router.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
在 store.js
文件中配置 Vuex store:
// store.js import { createStore } from 'vuex' export default createStore({ state: { todos: [] }, mutations: { addTodo(state, todo) { state.todos.push(todo) }, removeTodo(state, id) { state.todos = state.todos.filter(todo => todo.id !== id) } }, actions: { addTodo({ commit }, todo) { commit('addTodo', todo) }, removeTodo({ commit }, id) { commit('removeTodo', id) } }, getters: { todos: state => state.todos } })
在 components
目录下,创建一个 TodoItem.vue
组件,用于显示单个待办事项:
<!-- TodoItem.vue --> <template> <div class="todo-item"> <div>{{ todo.text }}</div> <button @click="removeTodo">Remove</button> </div> </template> <script> export default { name: 'TodoItem', props: { todo: Object }, methods: { removeTodo() { this.$emit('remove', this.todo.id) } } } </script> <style scoped> .todo-item { border: 1px solid #ccc; padding: 10px; margin-bottom: 10px; } </style>
创建 Home.vue
组件,用于显示待办事项列表:
<!-- Home.vue --> <template> <div> <h1>Todo List</h1> <input v-model="newTodo" @keyup.enter="addTodo" placeholder="Add a new todo"> <div v-for="todo in todos" :key="todo.id"> <TodoItem :todo="todo" @remove="removeTodo" /> </div> </div> </template> <script> import { mapState, mapActions } from 'vuex' import TodoItem from '../components/TodoItem.vue' export default { name: 'Home', components: { TodoItem }, data() { return { newTodo: '' } }, computed: { ...mapState(['todos']) }, methods: { addTodo() { if (this.newTodo.trim() !== '') { this.$store.dispatch('addTodo', { id: Date.now(), text: this.newTodo }) this.newTodo = '' } }, removeTodo(id) { this.$store.dispatch('removeTodo', id) } } } </script> <style scoped> input { width: 100%; padding: 10px; margin-bottom: 10px; } </style>
在 Home.vue
组件中,我们通过 this.$store.dispatch
调用 Vuex store 的 actions 方法来添加和删除待办事项,同时使用 v-model
和 v-for
指令来实现双向数据绑定和列表渲染。
最后,启动开发服务器,查看项目效果:
npm run serve
访问 http://localhost:8080
即可看到运行中的待办事项列表应用。
// router.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
// store.js import { createStore } from 'vuex' export default createStore({ state: { todos: [] }, mutations: { addTodo(state, todo) { state.todos.push(todo) }, removeTodo(state, id) { state.todos = state.todos.filter(todo => todo.id !== id) } }, actions: { addTodo({ commit }, todo) { commit('addTodo', todo) }, removeTodo({ commit }, id) { commit('removeTodo', id) } }, getters: { todos: state => state.todos } })
<!-- TodoItem.vue --> <template> <div class="todo-item"> <div>{{ todo.text }}</div> <button @click="removeTodo">Remove</button> </div> </template> <script> export default { name: 'TodoItem', props: { todo: Object }, methods: { removeTodo() { this.$emit('remove', this.todo.id) } } } </script> <style scoped> .todo-item { border: 1px solid #ccc; padding: 10px; margin-bottom: 10px; } </style>
<!-- Home.vue --> <template> <div> <h1>Todo List</h1> <input v-model="newTodo" @keyup.enter="addTodo" placeholder="Add a new todo"> <div v-for="todo in todos" :key="todo.id"> <TodoItem :todo="todo" @remove="removeTodo" /> </div> </div> </template> <script> import { mapState, mapActions } from 'vuex' import TodoItem from '../components/TodoItem.vue' export default { name: 'Home', components: { TodoItem }, data() { return { newTodo: '' } }, computed: { ...mapState(['todos']) }, methods: { addTodo() { if (this.newTodo.trim() !== '') { this.$store.dispatch('addTodo', { id: Date.now(), text: this.newTodo }) this.newTodo = '' } }, removeTodo(id) { this.$store.dispatch('removeTodo', id) } } } </script> <style scoped> input { width: 100%; padding: 10px; margin-bottom: 10px; } </style>
通过本教程的学习,我们掌握了 Vue3 的基本概念、项目搭建方法、组件化开发、路由与状态管理,以及生命周期方法的使用。结合一个简单的待办事项列表应用实例,我们进一步了解了这些概念在实际开发中的应用。希望本教程能够帮助你快速上手 Vue3,构建高效的前端应用。后续你可以通过官方文档和更多教程进一步深入学习 Vue3 的更多高级功能和最佳实践。