Vue.js 从入门到精通:全面解析组件化、路由与状态管理(附 Todo 案例)
在当今的前端开发领域,Vue.js 以其简洁、高效和灵活的特点受到了广泛的关注和应用。本文将带你从 Vue 的基础知识入手,逐步深入到高级特性,让你对 Vue 有一个全面的了解,并通过实际案例帮助你更好地掌握 Vue 的开发。
一、Vue 简介
Vue.js 是一个渐进式 JavaScript 框架,它专注于视图层,易于上手且非常灵活。Vue 的核心库只关注视图层,因此可以轻松地与其他库或现有项目集成。
二、环境搭建
-
安装 Node.js
Vue.js 需要 Node.js 环境来运行。你可以从Node.js 官方网站下载并安装适合你操作系统的版本。 -
安装 Vue CLI
Vue CLI 是一个官方提供的命令行工具,用于快速搭建 Vue 项目。打开终端并运行以下命令来安装 Vue CLI:
npm install -g @vue/cli
三、创建第一个 Vue 项目
1.使用 Vue CLI 创建项目
在终端中运行以下命令来创建一个新的 Vue 项目:
vue create my-vue-project
按照提示选择项目的配置选项,如使用 Vue 2 还是 Vue 3、是否安装路由和状态管理等。
2.项目结构
创建完成后,进入项目目录,可以看到以下主要的文件和目录:
src/
:项目的源代码目录。main.js
:入口文件,用于创建 Vue 实例。App.vue
:根组件文件。package.json
:项目的配置文件。
四、Vue 的基本语法
1.模板语法
Vue 使用模板语法来将数据渲染到 HTML 中。以下是一个简单的例子:
<template><div><h1>{{ message }}</h1></div></template><script>export default {data() {return {message: 'Hello, Vue!'};}};</script>
在上面的例子中,使用双大括号{{ message }}
来显示数据message
的值。
2.指令
Vue 提供了一些指令来增强 HTML 的功能。例如,v-if
和v-for
指令:
<template><div><ul><li v-for="item in items" :key="item.id">{{ item.name }}</li></ul><p v-if="showMessage">This message is visible.</p></div></template><script>export default {data() {return {items: [{ id: 1, name: 'Item 1' },{ id: 2, name: 'Item 2' },{ id: 3, name: 'Item 3' }],showMessage: true};}};</script>
在上面的例子中,使用v-for
指令遍历items
数组并渲染每个元素,使用v-if
指令根据showMessage
的值来决定是否显示<p>
元素。
五、组件化开发
1.创建组件
Vue 鼓励使用组件化开发,将页面拆分成多个可复用的组件。以下是一个简单的组件示例:
<template><div><h2>{{ title }}</h2><p>{{ content }}</p></div></template><script>export default {props: ['title', 'content'],};</script>
在上面的例子中,创建了一个名为MyComponent
的组件,它接受title
和content
两个属性。
2.使用组件
在其他组件或页面中,可以使用<component-name>
标签来引用组件,并通过属性传递数据:
<template><div><MyComponent title="Component Title" content="Component content." /></div></template><script>import MyComponent from './MyComponent.vue';export default {components: {MyComponent}};</script>
组件化开发的优势在于提高代码的可维护性和可复用性。通过将页面拆分成多个小的组件,可以更好地组织代码,使得每个组件的功能更加单一,易于理解和修改。同时,组件可以在不同的页面或项目中复用,减少了重复代码的编写。
组件通信
在 Vue 中,组件之间的通信有多种方式:
1.Props 传递数据:父组件向子组件传递数据可以通过 props 属性。子组件通过接收父组件传递过来的 props 来获取数据。
<!-- 父组件 --><template><div><ChildComponent :message="parentMessage" /></div></template><script>import ChildComponent from './ChildComponent.vue';export default {data() {return {parentMessage: 'Hello from parent'};},components: {ChildComponent}};</script><!-- 子组件 --><template><div><p>{{ message }}</p></div></template><script>export default {props: ['message']};</script>
2.触发事件:子组件向父组件传递数据可以通过触发自定义事件并使用emit` 方法。父组件在使用子组件时监听这个自定义事件来获取子组件传递过来的数据。
<!-- 父组件 --><template><div><ChildComponent @customEvent="handleCustomEvent" /></div></template><script>import ChildComponent from './ChildComponent.vue';export default {methods: {handleCustomEvent(data) {console.log(data);}},components: {ChildComponent}};</script><!-- 子组件 --><template><div><button @click="emitEvent">Emit Event</button></div></template><script>export default {methods: {emitEvent() {this.$emit('customEvent', 'Data from child');}}};</script>
3.Vuex 状态管理:对于复杂的应用,多个组件之间需要共享数据时,可以使用 Vuex 进行状态管理。Vuex 提供了一个集中式的存储,使得组件可以方便地获取和修改共享状态。
六、路由管理
1.安装 Vue Router
Vue Router 是 Vue.js 的官方路由管理器。在项目中安装 Vue Router:
npm install vue-router
2.配置路由
创建一个router.js
文件来配置路由:
import Vue from 'vue';import VueRouter from 'vue-router';import Home from './views/Home.vue';import About from './views/About.vue';Vue.use(VueRouter);const routes = [{path: '/',name: 'Home',component: Home},{path: '/about',name: 'About',component: About}];const router = new VueRouter({mode: 'history',routes});export default router;
在上述代码中,首先导入Vue
、VueRouter
以及两个视图组件Home.vue
和About.vue
。然后使用Vue.use(VueRouter)
安装路由插件。接着定义了一个路由数组routes
,其中每个对象代表一个路由,包括路径path
、路由名称name
和对应的组件component
。最后,创建一个VueRouter
实例并将其导出。
3.使用路由
在main.js
文件中引入路由并将其挂载到 Vue 实例上:
import Vue from 'vue';import App from './App.vue';import router from './router';Vue.config.productionTip = false;new Vue({render: h => h(App),router}).$mount('#app');
在组件中,可以使用<router-link>
标签来导航到不同的路由,使用<router-view>
标签来显示当前路由对应的组件:
<template><div><nav><router-link to="/">Home</router-link><router-link to="/about">About</router-link></nav><router-view></router-view></div></template>
<router-link>
标签会生成一个链接,点击链接时会导航到对应的路由。<router-view>
标签是一个占位符,用于显示当前路由对应的组件。
路由参数和查询参数
1.路由参数:可以在路由中定义参数,以便在不同的页面之间传递特定的值。例如:
const routes = [{path: '/user/:id',name: 'User',component: User}];
在组件中,可以通过this.$route.params.id
来获取路由参数的值。
2.查询参数:可以在路由链接中添加查询参数,用于传递额外的信息。例如:
<router-link :to="{ path: '/user', query: { id: 123 } }">User Page</router-link>
在组件中,可以通过this.$route.query.id
来获取查询参数的值。
路由导航守卫
路由导航守卫可以在路由切换的不同阶段进行拦截和控制。主要有以下几种导航守卫:
1.全局前置守卫:在路由切换之前执行,可以用于判断用户是否登录等权限控制。
router.beforeEach((to, from, next) => {// 判断用户是否登录if (to.meta.requiresAuth &&!isLoggedIn()) {next('/login');} else {next();}});
2.全局后置守卫:在路由切换之后执行,可以用于统计页面访问等操作。
router.afterEach((to, from) => {// 统计页面访问trackPageView(to.fullPath);});
3.组件内守卫:可以在组件内定义beforeRouteEnter
、beforeRouteUpdate
和beforeRouteLeave
守卫,分别在进入组件、路由参数变化和离开组件时执行。
export default {beforeRouteEnter(to, from, next) {// 在进入组件之前执行next(vm => {// 可以访问组件实例 vm});},beforeRouteUpdate(to, from, next) {// 在路由参数变化时执行next();},beforeRouteLeave(to, from, next) {// 在离开组件之前执行next();}};
七、状态管理
1.安装 Vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。安装 Vuex:
npm install vuex
2.配置 Vuex
创建一个store.js
文件来配置 Vuex:
import Vue from 'vue';import Vuex from 'vuex';Vue.use(Vuex);const store = new Vuex.Store({state: {count: 0},mutations: {increment(state) {state.count++;}},actions: {increment(context) {context.commit('increment');}},getters: {doubleCount(state) {return state.count * 2;}}});export default store;
在上述代码中,首先导入Vue
和Vuex
,然后使用Vue.use(Vuex)
安装状态管理插件。接着创建一个Vuex.Store
实例,其中包含状态state
、 mutations、 actions 和 getters。
state
:存储应用的状态数据。mutations
:定义了修改状态的方法,只能通过提交 mutation 来修改状态。actions
:用于处理异步操作,可以提交 mutation 来修改状态。getters
:可以从状态中派生出一些计算属性,方便在组件中使用。
3.使用 Vuex
在组件中,可以通过this.$store
来访问 Vuex 状态和方法:
<template><div><p>Count: {{ count }}</p><p>Double Count: {{ doubleCount }}</p><button @click="increment">Increment</button></div></template><script>export default {computed: {count() {return this.$store.state.count;},doubleCount() {return this.$store.getters.doubleCount;}},methods: {increment() {this.$store.dispatch('increment');}}};</script>
在上述代码中,通过计算属性count
和doubleCount
分别访问Vuex
中的状态和计算属性。在methods
中定义了一个方法increment
,用于触发Vuex
中的 action。
模块
对于大型应用,可以将 Vuex 的状态拆分成多个模块,每个模块有自己的 state、mutations、actions 和 getters。这样可以更好地组织代码,提高可维护性。
const moduleA = {state: {// 模块 A 的状态},mutations: {// 模块 A 的 mutations},actions: {// 模块 A 的 actions},getters: {// 模块 A 的 getters}
};const moduleB = {state: {// 模块 B 的状态},mutations: {// 模块 B 的 mutations},actions: {// 模块 B 的 actions},getters: {// 模块 B 的 getters}
};const store = new Vuex.Store({modules: {a: moduleA,b: moduleB}
});
在组件中访问模块的状态和方法时,需要加上模块名:
<template><div><p>Module A Count: {{ moduleACount }}</p><p>Module B Count: {{ moduleBCount }}</p><button @click="incrementModuleA">Increment Module A</button><button @click="incrementModuleB">Increment Module B</button></div>
</template><script>
export default {computed: {moduleACount() {return this.$store.state.a.count;},moduleBCount() {return this.$store.state.b.count;}},methods: {incrementModuleA() {this.$store.dispatch('a/increment');},incrementModuleB() {this.$store.dispatch('b/increment');}}
};
</script>
八、案例:Todo 应用
下面我们通过一个 Todo 应用的案例来综合运用 Vue 的知识。
-
创建组件
创建以下组件:TodoList.vue
:显示待办事项列表。TodoInput.vue
:输入新的待办事项。
-
配置路由
创建两个路由:/
和/completed
,分别显示所有待办事项和已完成的待办事项。 -
状态管理
使用 Vuex 来管理待办事项的状态,包括添加、删除、标记为完成等操作。 -
实现功能
- 在
TodoInput.vue
组件中,用户可以输入新的待办事项并提交。 - 在
TodoList.vue
组件中,显示待办事项列表,每个待办事项可以被标记为完成或删除。 - 在路由
/completed
中,只显示已完成的待办事项。
- 在
以下是部分代码示例:
TodoInput.vue
<template><div><input v-model="newTodo" @keyup.enter="addTodo" placeholder="Add a new todo" /></div>
</template><script>
export default {data() {return {newTodo: ''};},methods: {addTodo() {if (this.newTodo.trim()) {this.$store.dispatch('addTodo', this.newTodo);this.newTodo = '';}}}
};
</script>
TodoList.vue
<template><div><ul><li v-for="todo in todos" :key="todo.id"><input type="checkbox" v-model="todo.completed" @change="toggleTodo(todo)" />{{ todo.text }}<button @click="deleteTodo(todo)">Delete</button></li></ul></div>
</template><script>
export default {computed: {todos() {return this.$store.state.todos;}},methods: {toggleTodo(todo) {this.$store.dispatch('toggleTodo', todo);},deleteTodo(todo) {this.$store.dispatch('deleteTodo', todo);}}
};
</script>
store.js
import Vue from 'vue';
import Vuex from 'vuex';Vue.use(Vuex);const store = new Vuex.Store({state: {todos: []},mutations: {addTodo(state, text) {state.todos.push({ id: Date.now(), text, completed: false });},toggleTodo(state, todo) {todo.completed =!todo.completed;},deleteTodo(state, todo) {state.todos = state.todos.filter(item => item!== todo);}},actions: {addTodo(context, text) {context.commit('addTodo', text);},toggleTodo(context, todo) {context.commit('toggleTodo', todo);},deleteTodo(context, todo) {context.commit('deleteTodo', todo);}}
});export default store;
router.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import TodoList from './views/TodoList.vue';
import CompletedTodos from './views/CompletedTodos.vue';Vue.use(VueRouter);const routes = [{path: '/',name: 'TodoList',component: TodoList},{path: '/completed',name: 'CompletedTodos',component: CompletedTodos}
];const router = new VueRouter({mode: 'history',routes
});export default router;
CompletedTodos.vue
<template><div><h2>Completed Todos</h2><ul><li v-for="todo in completedTodos" :key="todo.id">{{ todo.text }}</li></ul></div>
</template><script>
export default {computed: {completedTodos() {return this.$store.state.todos.filter(todo => todo.completed);}}
};
</script>
通过这个案例,你可以看到如何使用 Vue 的组件化、路由管理和状态管理来构建一个完整的应用程序。
九、总结
本文介绍了 Vue.js 的基础知识和高级特性,并通过一个 Todo 应用的案例展示了如何综合运用这些知识。Vue.js 是一个非常强大的前端框架,通过不断学习和实践,你可以更好地掌握它,并开发出高效、美观的前端应用程序。
希望本文对你学习 Vue.js 有所帮助!
相关文章:
Vue.js 从入门到精通:全面解析组件化、路由与状态管理(附 Todo 案例)
在当今的前端开发领域,Vue.js 以其简洁、高效和灵活的特点受到了广泛的关注和应用。本文将带你从 Vue 的基础知识入手,逐步深入到高级特性,让你对 Vue 有一个全面的了解,并通过实际案例帮助你更好地掌握 Vue 的开发。 一、Vue 简…...

AI Weekly#1:过去一周重要的AI资讯汇总
🚀热点头条 诺贝尔奖青睐AI领域:2024年诺贝尔物理学奖和化学奖均授予了与人工智能相关的研究。物理学奖颁发给了约翰霍普菲尔德和杰弗里辛顿,表彰他们在机器学习领域的开创性工作。化学奖则授予了大卫贝克、德米斯哈萨比斯和约翰江珀…...
图论刷题
卡码网 98. 所有可达路径 使用邻接矩阵存储: #include<iostream> #include<vector> using namespace std;vector<vector<int>>res;//收集符合条件的路径vector<int>path;//0节点到终点的路径//确定递归函数 参数和返回值void dfs(c…...
ICM20948 DMP代码详解(85)
接前一篇文章:ICM20948 DMP代码详解(84) 上一回解析了inv_icm20948_ctrl_enable_sensor函数的大部分代码,只剩下一行代码没有解析。为了便于理解和回顾,再次贴出inv_icm20948_ctrl_enable_sensor函数源码,在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948Data…...
深入解析:Linux tcpdump命令在网络流量分析中的实战应用
tcpdump是一个强大的命令行工具,用于捕获和分析TCP、UDP、ICMP等协议的网络流量。 功能与用途 捕获网络流量:tcpdump可以捕获和显示来自本地计算机或通过网络传输的数据包,提供有关数据包的详细信息,如源和目的IP地址、端口号、…...

Java集合常见知识总结(上)
Java 集合概览 Java 集合,也叫作容器,主要是由两大接口派生而来:一个是 Collection接口,主要用于存放单一元素;另一个是 Map 接口,主要用于存放键值对。对于Collection 接口,下面又有三个主要的…...

【算法】力扣:K个一组反转链表
前置知识 数据结构-链表反转部分链表算法题的手写栈使用 难度: 初阶:使用容器, 难度中等。进阶:纯coding修改指针 ,难度中等,虽然leetcode是困难题。不过更加注重细节。 题目:反转 k 组中的…...

Matlab报错——错误使用 vertcat
错误提示: 原因: 这个错误表明 segment_lengths 的维度和 0 不一致。在 MATLAB 中,有时,diff 函数的输出可能是行向量,而segment_lengths 应该是一个列向量才能与 0 正确连接。 解决方法: 使用转置操作 …...
【如何获取股票数据10】Python、Java等多种主流语言实例演示获取股票行情api接口之沪深A股历史分时KDJ数据获取实例演示及接口API说明文档
最近一两年内,股票量化分析逐渐成为热门话题。而从事这一领域工作的第一步,就是获取全面且准确的股票数据。因为无论是实时交易数据、历史交易记录、财务数据还是基本面信息,这些数据都是我们进行量化分析时不可或缺的宝贵资源。我们的主要任…...

进入 Searing-66 火焰星球:第一周游戏指南
Alpha 第四季已开启,穿越火焰星球 Searing-66,带你开启火热征程。准备好勇闯炙热的沙漠,那里有无情的高温和无情的挑战在等待着你。从高风险的烹饪对决到炙热的冒险,Searing-66 将把你的耐力推向极限。带上充足的水,天…...

考研论坛设计小程序ssm+论文源码调试讲解
2相关技术 2.1微信小程序 小程序是一种新的开放能力,开发者可以快速地开发一个小程序。小程序可以在微信内被便捷地获取和传播,同时具有出色的使用体验。尤其拥抱微信生态圈,让微信小程序更加的如虎添翼,发展迅猛。 2.2 MYSQL数据…...
JAVA笔记 | EasyExcel创建带有简单下拉框的导入模板
目录 前文 业务需求 具体代码 新增Handler 控制层 前文 SpringBoot笔记 | EasyExcel导入导出及基于模板导出_easyexcel模板导出-CSDN博客 业务需求 需要一个导出模板。一个列需要填写固定的值,或者方便用户填写。 自己需求,几个固定的字段对应固…...

【含开题报告+文档+PPT+源码】贫困儿童一对一扶贫帮扶系统设计与实现
开题报告 根据《中华人民共和国慈善法》第五十八条规定,慈善组织确定慈善受益人,应当坚持公开、公平、公正的原则,不得指定慈善组织管理人员的利害关系人作为受益人[2]。以上所列举的平台基本没有做到公开、公平、公正的原则,例如…...

多系统萎缩不慌张,这些维生素是你的“隐形盾牌”!️
在这个快节奏的时代,健康成为了我们最宝贵的财富。而对于多系统萎缩(MSA)的患者来说,合理的营养补充更是维护身体机能、提升生活质量的关键一步。今天,就让我们一起揭秘那些能够成为多系统萎缩患者“守护神”的维生素吧…...

IGFBP7:免疫治疗新靶点
前 言 胰岛素样生长因子结合蛋白7(IGFBP7)是胰岛素超家族的生长促进肽成员,可与胰岛素和IGF结合,调控细胞生长和分化。IGFBP7在不同的肿瘤类型中表现出抑制或促进肿瘤生长的“自相矛盾”活性。研究发现IGFBP7可增强治疗性单克隆…...
深度学习模型的架构与应用:技术解析与未来展望
1. 引言 深度学习(Deep Learning)模型是当代人工智能的核心技术之一,广泛应用于语音识别、计算机视觉、自然语言处理、推荐系统等众多领域。深度学习通过构建多层神经网络,能够自动从大规模数据中学习复杂的特征和模式,其应用成果不仅推动了技术的飞跃,也带来了智能化产…...
机器学习——主要分类
前言: 机器学习是人工智能的重要分支之一,它通过分析数据来构建模型,并通过这些模型进行预测、分类或决策。随着数据量的迅速增长,机器学习在多个领域展现出巨大的应用潜力,推动了科技的进步。根据学习方式和数据的使用…...
Java密封类(Sealed Classes)增强详解
Java密封类(Sealed Classes)增强详解 Java 17引入了一个重要的新特性——密封类(Sealed Classes),这一特性旨在增强Java编程语言的能力,提供了一种机制来限制哪些类可以继承一个给定的类或者实现一个给定的…...

鸿蒙如何自动生成二维码?QRCode组件
QRCode 用于显示单个二维码的组件。 说明: 该组件从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 二维码组件的像素点数量与内容有关,当组件尺寸过小时,可能出现无法展示内容的情况&…...

【分布式知识】MapReduce详细介绍
文章目录 MapReduce概述1. MapReduce编程模型Map阶段Reduce阶段 2. Shuffle和Sort阶段3. MapReduce作业的执行流程4. MapReduce的优化和特性5. MapReduce的配置和调优 MapReduce局限性相关文献 MapReduce概述 MapReduce是一个分布式计算框架,它允许用户编写可以在大…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...

stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
深入理解Optional:处理空指针异常
1. 使用Optional处理可能为空的集合 在Java开发中,集合判空是一个常见但容易出错的场景。传统方式虽然可行,但存在一些潜在问题: // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...

windows系统MySQL安装文档
概览:本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容,为学习者提供全面的操作指导。关键要点包括: 解压 :下载完成后解压压缩包,得到MySQL 8.…...
React父子组件通信:Props怎么用?如何从父组件向子组件传递数据?
系列回顾: 在上一篇《React核心概念:State是什么?》中,我们学习了如何使用useState让一个组件拥有自己的内部数据(State),并通过一个计数器案例,实现了组件的自我更新。这很棒&#…...
背包问题双雄:01 背包与完全背包详解(Java 实现)
一、背包问题概述 背包问题是动态规划领域的经典问题,其核心在于如何在有限容量的背包中选择物品,使得总价值最大化。根据物品选择规则的不同,主要分为两类: 01 背包:每件物品最多选 1 次(选或不选&#…...

C# WPF 左右布局实现学习笔记(1)
开发流程视频: https://www.youtube.com/watch?vCkHyDYeImjY&ab_channelC%23DesignPro Git源码: GitHub - CSharpDesignPro/Page-Navigation-using-MVVM: WPF - Page Navigation using MVVM 1. 新建工程 新建WPF应用(.NET Framework) 2.…...