前端学习笔记 3:Vue 工程

前端学习笔记 3:Vue 工程

上一篇文章介绍了如何在单一 Html 页面中使用 Vue,本文介绍如何从头开始用 Vue 构建一个前端工程项目。

环境准备

Vue 框架代码的创建依赖于 Node.js,因此需要先安装 Node.js。

创建和启动

创建

通过以下命令可以创建 Vue 的框架代码:

npm create vue@latest
  • 该命令执行后会先检查是否安装 create-vue 工具,如果没有,就安装。然后再使用 create-vue 创建框架代码。
  • npm(Node Package Manager)是 NodeJS 的包管理工具,类似于 Linux 的 RPM 或 YUM。

在执行过程中会询问是否启用一些功能模块:

Vue.js - The Progressive JavaScript Framework√ 请输入项目名称: ... vue-project
√ 是否使用 TypeScript 语法? ... 否 / 是
√ 是否启用 JSX 支持? ... 否 / 是
√ 是否引入 Vue Router 进行单页面应用开发? ... 否 / 是
√ 是否引入 Pinia 用于状态管理? ... 否 / 是
√ 是否引入 Vitest 用于单元测试? ... 否 / 是
√ 是否要引入一款端到端(End to End)测试工具? » 不需要
√ 是否引入 ESLint 用于代码质量检测? ... 否 / 是

默认是

安装好框架代码后,还需要进入工程目录安装相关依赖:

cd .\vue-project\
npm install

启动

执行npm run dev命令可以启动 Vue 项目:

VITE v5.0.10  ready in 2711 ms➜  Local:   http://localhost:5173/
➜  Network: use --host to expose
➜  press h + enter to show help

就像控制台提示信息中显示的,运行 Vue 项目的 Nodejs 服务端地址默认是 http://localhost:5173/,前往该地址就能看到一个默认的欢迎页面。

除了命令行启动外,还可以用 VSCode 启动:

image-20231231190912113

如果界面上没有 NPM 脚本 这一栏,可以通过这里开启:

image-20231231191034895

快速开始

下面简单分析一下工程默认的欢迎页的显示逻辑。

实际上浏览器访问时加载的是index.html文件:

image-20231231192645949

该文件通过<script type="module" src="/src/main.js"></script>这行代码以模块化的方式加载了 JS 文件/src/main.js

image-20231231192815009

main.js中,通过import { createApp } from 'vue'导入了 Vue 的createApp函数,与之前不同的是,因为已经用 npm 工具安装了本地依赖(npm install),所以这里是通过本地导入,而非从在线的 JS 文件导入 Vue 函数。

npm 安装的本地依赖模块位于node_modules目录下。

这里最重要的是import App from './App.vue',从App.vue文件导入了一个 App 对象,之后的代码createApp(App).mount('#app')使用该对象作为参数创建了 Vue 实例。

App.vue文件包含三部分:

image-20231231193442841

事实上,在开发基于 Vue 的前端项目时,我们主要工作是创建和修改 Vue 文件。

作为示例,这里可以创建一个Hello.vue

<template><h1>Hello World!</h1>
</template>
<style>
h1 {color: aqua;
}
</style>

要在页面中显示,还需要在main.js中替换导入代码:

import App from './Hello.vue'

在 Vue 文件中同样可以像前文那样为 Vue 实例提供数据和方法:

<script>
export default {data() {return {msg: 'Hello World!'}}
}
</script>
<template><h1>{{ msg }}</h1>
</template>

这里通过export default {...}指定了Hello.vue文件默认导出的对象内容,该对象会在main.js中导入为App对象,也就是用于创建 Vue 实例的参数对象,因此我们可以在export default {...}定义的默认导出对象中定义datamethods等 Vue 需要的方法或属性。

除了上面的方式外,还可以借助ref函数定义数据或方法:

<script setup>
import {ref} from 'vue'
const msg = ref('Hello World!')
</script>

注意,这里的scriptsetup属性。

API 风格

Vue 的 API 有两种风格,这里分别用两种风格编写同样的功能页面进行说明。

选项式

定义一个 Count.vue 文件:

<script>
export default {data() { //定义响应式数据return {num: 0}},methods: { // 定义 Vue 方法count() {this.num++;}},mounted(){ // 定义钩子函数console.log("Vue 实例已加载...")}
}
</script>
<template><button @click="count">count:{{ num }}</button>
</template>

要让该文件生效,还要在Hello.vue中导入:

<script setup>
import {ref} from 'vue'
const msg = ref('Hello World!')
import Count from './Count.vue'
</script>
<template><h1>{{ msg }}</h1><br/><Count/>
</template>

注意 >Count/> 标签,该标签的位置代表 Count.vue 文件中的模版插入的位置。

选项式的优点在于结构简单,便于理解,缺点是代码结构过于死板,不够灵活。

组合式

<script setup>
import { ref, onMounted } from 'vue'
// 定义响应式数据
const num = ref(0)
// 定义 Vue 方法
function count() {num.value++;
}
// 定义钩子函数
onMounted(() => {console.log("Vue 实例已加载...")
})
</script>
<template><button @click="count">count:{{ num }}</button>
</template>

在组合式 API 中,需要用ref函数定义响应式数据,用特定的函数(比如 onMounted)定义 Vue 生命周期的钩子方法。特别需要注意的是,组合式 API 中,ref定义的响应式数据有一个value属性,表示响应式数据的值,因此这里在count函数中,自增使用的是num.value++而非num++

案例

下面是一个简单案例,用 Vue 工程的方式创建一个ArticleList.vue,用于展示文章列表和搜索框。

在编写这个 Vue 文件之前,需要先在本地安装 axios 的依赖:

npm install axios

下面是ArticleList.vue的完整内容:

<script setup>
import { ref, onMounted } from 'vue'
import axios from 'axios'
// 创建表格对应的响应式数据
const articles = ref([])
// Vue 实例初始化后加载表格数据
onMounted(() => {axios.get("http://localhost:8080/article/getAll").then(result => {articles.value = result.data}).catch(error => {console.log(error)})
})
// 创建搜索条件对应的响应式数据
const conditions = ref({category: '',state: ''
})
// 定义搜索绑定事件
const search = () => {axios.get("http://localhost:8080/article/search", { params: {...conditions.value} }).then(result => {articles.value = result.data}).catch(error => {console.log(error)})
} 
</script>
<template><div>文章分类:<input type="text" v-model="conditions.category"/>发布状态:<input type="text" v-model="conditions.state"/><button @click="search">搜索</button><br /><br /><table border="1"><tr><td>文章标题</td><td>分类</td><td>发表时间</td><td>状态</td><td>操作</td></tr><tr v-for="article in articles"><td>{{ article.title }}</td><td>{{ article.category }}</td><td>{{ article.time }}</td><td>{{ article.state }}</td><td><button>编辑</button><button>删除</button></td></tr></table></div>
</template>

注意,这里search函数内调用axios.get方法传参时使用了 ES6 的解构赋值:

{ params: {...conditions.value} }

这样可以让代码更简洁。

当然你也可以使用传统匿名函数分别给属性赋值的方式。

封装函数

上面的案例有一个缺陷——通过 Axios 调用接口获取数据的部分没有单独封装成函数,这样不利于其它部分的代码进行复用。更好的做法是将这些会被复用的逻辑抽取成单独的函数保存在单独的 JS 文件中,在需要使用的地方导入所需的函数并进行调用。

首先在src目录下创建一个/api/article.js文件:

import axios from 'axios'export async function getAllArticlesService(){return await axios.get("http://localhost:8080/article/getAll").then(result => {return result.data}).catch(error => {console.log(error)})
}

ArticleList.vue 进行重构:

import { getAllArticlesService } from '@/api/article.js'
// ...
// Vue 实例初始化后加载表格数据
onMounted(async () => {articles.value = await getAllArticlesService()
})

需要注意的是,这里使用了awaitasync关键字,这是因为抽取后的函数getAllArticlesService中的axios.get本质上是异步调用,因此没办法同步地获取其返回值,所以需要在调用时添加await关键字将其变成同步调用,而此时进行调用的函数(getAllArticlesService)本身变成了异步,所以要添加async关键字。同理,在调用onMounted钩子方法时,同样需要给作为参数的匿名函数加上async,并且在其中的getAllArticlesService调用加上await

  • 如果不使用awaitasync,就不会有任何数据加载。因为异步调用的关系,响应式数据的赋值语句实际上还没有等到异步调用执行并返回就已经被主线程执行完毕,所以不会有任何实际数据被赋值。
  • 在导入时,如果导入的是本地src目录下的资源,可以使用@/代表src目录。

搜索文章相关调用同样可以进行封装,这里不再赘述。

axios 实例

上面的案例还存在一个瑕疵,单个 JS 文件中的多次 Axios 调用实际上使用的是相同的服务端域名(HOST),只是具体的接口路径不同。针对这个问题,可以使用 Axios 实例进行简化和统一设置:

import axios from 'axios'
const instance = axios.create({baseURL: 'http://localhost:8080'
});export async function getAllArticlesService() {return await instance.get("/article/getAll").then(result => {return result.data}).catch(error => {console.log(error)})
}

axios 拦截器

使用axios进行异步请求时,往往需要对响应结果进行相似的处理,比如:

instance.get("/article/getAll").then(result => {return result.data}).catch(error => {console.log(error)})

对此,可以创建一个单独的 axios 实例进行复用,并且在这个实例上定义请求/响应拦截器对请求或响应进行统一处理。

添加/util/request.js

import axios from 'axios'
const instance = axios.create({baseURL: 'http://localhost:8080'
});
instance.interceptors.response.use(result => {return result.data},error => {console.log(error)return Promise.reject(error);}
)
export default instance

interceptors.response.use用于设置响应拦截器,接收两个参数,分别为调用成功(HTTP 状态码 2XX)和调用失败(HTTP 状态码不是 2XX)时的回调函数。

article.js中导入:

import request from '@/util/request.js'export async function getAllArticlesService() {return await request.get("/article/getAll")
}export async function searchService(conditions) {return await request.get("/article/search", { params: conditions })
}

因为实例request设置了响应拦截器对结果进行统一处理,所以这里不需要再使用.then.catch进行处理。

实际上内层的awaitasync关键字是可以省略的,只要最外层调用有即可:

import request from '@/util/request.js'export function getAllArticlesService() {return request.get("/article/getAll")
}export function searchService(conditions) {return request.get("/article/search", { params: conditions })
}

谢谢阅读,本文的完整示例代码见这里。

参考资料

  • 1.1 ES6 教程 | 菜鸟教程 (runoob.com)
  • 拦截器 | Axios中文文档 | Axios中文网 (axios-http.cn)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/591275.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring通信传参的方法

Spring通信传参的方法 目录概述需求&#xff1a; 设计思路实现思路分析1.简单参数传递2.复合参数3.动态参数 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better resul…

HarmonyOS UI框架简介

HarmonyOS UI框架介绍 HarmonyOSUI框架是一个用于构建跨设备应用的开发框架&#xff0c;它属于HarmonyOS系统架构的上层框架。该框架通过提供一系列的开发模型、声明式UI范式、系统API等&#xff0c;帮助开发者更高效地构建用户界面。 在HarmonyOSUI框架中&#xff0c;开发语…

C#中字母与ASCⅡ码的转换

目录 一、关于ASCⅡ及与字符互转 1.主要用到Encoding对象的GetBytes方法 2.Char显式转换为数值类型得到ASCⅡ 二、实例 三、生成效果 四、程序中的一些知识点 1.IsLetterOrDigit() 2.GetBytes() 3.TryParse(string, out int) 一、关于ASCⅡ及与字符互转 ASCⅡ(Americ…

.net8时代,微软.net开发策略,F#不就是VB语言吗?

看了一下F#代码几乎和VB差不多&#xff0c;重复造轮子微软却玩的很开心。 可是真正的VB6,vb.net却抛弃了 .网络管理语言策略。NET微软学习https://learn.microsoft.com/en-us/dotnet/fundamentals/languages 微软提供三种语言。网络平台-C#,F#和视觉基础.在本文中,您将了解我…

计算机网络的接口

计算机网络接口是计算机与网络通信设备之间进行通信的重要部分&#xff0c;它提供了计算机连接到网络的物理和逻辑接口&#xff0c;是计算机进行网络通信的重要组成部分。本文将介绍计算机网络接口的基本概念&#xff0c;不同类型的网络接口及其特点&#xff0c;以及在实际应用…

KBDNO1.DLL文件缺失,软件或游戏无法启动运行,怎样快速修复

不少小伙伴&#xff0c;求助电脑报错“KBDNO1.DLL文件缺失&#xff0c;软件或游戏无法启动或运行”&#xff0c;应该怎么办&#xff1f; 首先&#xff0c;我们先来了解“KBDNO1.DLL文件”是什么&#xff1f; KBDNO1.DLL是Windows操作系统中的一个动态链接库文件&#xff0c;主…

连接progressql报错Cannot load JDBC driver class ‘org.postgresql.Driver‘,亲测有效!!!

Jmeter连接progressql报错Cannot load JDBC driver class ‘org.postgresql.Driver’ 1.到官方下载驱动注意&#xff1a;根据项目的JDK版本来下载对应的驱动Download | pgJDBC 2.将postgresql-42.2.27.jar复制到lib目录下面&#xff0c; 然后重新启动 连接driver信息如下&#…

【LeetCode:69. x 的平方根 | 二分】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

印尼小胖子表情包大全

印尼小胖子tatan表情包大全 想要更多表情包&#xff0c;访问cmay表情包大全

二叉树的前序遍历 、二叉树的最大深度、平衡二叉树、二叉树遍历(leetcode)

目录 一、二叉树的前序遍历 方法一&#xff1a;全局变量记录节点个数 方法二&#xff1a;传址调用记录节点个数 二、二叉树的最大深度 三、平衡二叉树 四、二叉树遍历 一、二叉树的前序遍历 方法一&#xff1a;全局变量记录节点个数 计算树的节点数: 函数TreeSize用于递…

java基础-回忆性记录3

运算符 算数运算符 运算符对常量或者变量进行操作的符号。 运算符吧常量或者变量连接起来符合java语法的式子可以称为表达式。 不同运算符连接表达式体现是不同类型。 符号作用说明加-减*乘/除%取余获取的是两个数据做除法的余数 注意&#xff1a; /和%的区别&#xff1a…

机器视觉在医学影像与医疗领域的应用及前景

引言 随着人工智能技术的飞速发展&#xff0c;机器视觉在医学影像和医疗领域中扮演着越来越重要的角色。机器视觉技术如何在医院领域提高诊断准确性、加快治疗流程以及改善患者体验。本文将探讨机器视觉算法的重要性、使用场景&#xff0c;并对其在医院领域应用的前景提出个人见…

Linux mdu命令教程:如何有效地使用mdu命令(附实例教程和注意事项)

Linux mdu命令介绍 mdu命令是Linux系统中的一个命令&#xff0c;全称为My Disk Usage&#xff0c;它用于显示目录或文件所占用的磁盘空间。 Linux mdu命令适用的Linux版本 mdu命令在大多数Linux发行版中都可以使用&#xff0c;包括但不限于Ubuntu, Debian, Fedora, CentOS等…

【PHP】获取 URL 中域名后的路径

目录 1.指定的url 2.当前请求的url 1.指定的url 如果您想从指定的 URL 中获取域名后的路径&#xff0c;可以使用 PHP 的 parse_url() 函数。以下是一个示例&#xff0c;展示了如何从指定的 URL 中获取域名后的路径&#xff1a; <?php$url https://example.com/path/to/r…

第83讲:MySQL数据库备份工具及备份策略的核心概念

文章目录 1. MySQL数据库库数据备份的理念2.MySQL数据库备份工具介绍3.逻辑备份与物理备份的比较4.数据库的备份策略 1. MySQL数据库库数据备份的理念 数据备份是作为运维来说必不可少的一个环节&#xff0c;无论是数据库数据、程序中间件都需要定期备份。 在进行备份之前首先…

计算机毕业设计-----SSM场地预订管理系统

项目介绍 本项目分为前后台&#xff0c;前台为普通用户登录&#xff0c;后台为管理员登录&#xff1b; 用户角色包含以下功能&#xff1a; 按分类查看场地,用户登录,查看网站公告,按分类查看器材,查看商品详情,加入购物车,提交订单,查看订单,修改个人信息等功能。 管理员角…

分布式【Zookeeper】

1.1 ZooKeeper 是什么 ZooKeeper 是 Apache 的顶级项目。ZooKeeper 为分布式应用提供了高效且可靠的分布式协调服务&#xff0c;提供了诸如统一命名服务、配置管理和分布式锁等分布式的基础服务。在解决分布式数据一致性方面&#xff0c;ZooKeeper 并没有直接采用 Paxos 算法&…

爬虫工作量由小到大的思维转变---<第三十四章 Scrapy 的部署scrapyd+Gerapy>

前言: scrapy-redis没被部署,感觉讲起来很无力;因为实在编不出一个能让scrapy-redis发挥用武之地的案子;所以,索性直接先把分布式爬虫的部署问题给讲清楚!! 然后,曲线救国式地再在部署的服务器上,讲scrapy redis我感觉这样才好! 正文: 现在还有不少人在用scrapy web进行爬虫管…

【深入探索Python库】操作系统功能的接口OS库(2)

系列文章目录 深入探索Python库之操作系统功能的接口OS库&#xff08;1&#xff09; 深入探索Python库之操作系统功能的接口OS库&#xff08;2&#xff09; 文章目录 系列文章目录引言系统信息进程管理结论 引言 前篇文章介绍了python库中os库的核心用途&#xff0c;包括文件…

2024,启动(回顾我的2023)

零.前言 打开博客想写个年度总结&#xff0c;发现已经半年没有更新文章了&#xff0c;排名从几千掉到了几万&#xff0c;不过数据量还是不错的。 时间过得可真快&#xff0c;2023年是充满动荡的一年&#xff0c;上半年gpt横空出世&#xff0c;下半年各种翻车暴雷吃瓜吃到嘴软…