云图库平台(二)前端项目初始化

news/2024/12/23 8:37:45/

环境准备:

  • node.js版本必须>=18.12,使用vue脚手架来初始化创建项目

目录

  • 一、创建项目
  • 二、前期准备
    • 前端工程化配置
    • 组件库的引入
    • 开发规范
  • 三、页面基本信息
    • 基础布局结构
    • 全局底部栏
    • 动态替换内容弄个
    • 全局顶部栏
      • 修改GlobalHeader组件
  • 四、路由
    • 路由跳转
    • 代码高亮实现
  • 五、Axios请求库
    • 全局自定义请求
    • 自动生成请求代码
    • 测试请求
  • 六、全局状态管理
    • 定义状态
    • 引入状态
    • 测试全局状态管理

一、创建项目

使用Vue的脚手架快速创建项目,可以参考Vue官网:https://cn.vuejs.org/

终端执行命令:

npm create vue@latest

在这里插入图片描述
项目创建完成后,这里我是使用的WebStorm打开的项目,在终端输入命令安装依赖:

npm install

在这里插入图片描述

依赖安装完成后运行npm run dev看是否能运行成功。
在这里插入图片描述
在这里插入图片描述
出现上述界面就说明运行成功了。

二、前期准备

前端工程化配置

刚刚使用vue脚手架创建项目时已经帮我们整合了Prettier代码美化ESLint自动校验TypeScript类型校验。但是我们需要在webstorm中开启代码美化插件.

setting->eslint:这里新手推荐选择第一个Disable ESLint,因为ESLing自动校验较为严格,对新手不是特别友好.在这里插入图片描述
setting->Prettier:开启代码美化工具,配置如下:
在这里插入图片描述

组件库的引入

引入Ant Design Vue组件库,这里使用的版本是v4.2.6,可以参考官方文档快速上手:https://antdv.com/docs/vue/getting-started-cn]

  • 输入命令引入组件
npm i --save ant-design-vue@4.x

在这里插入图片描述

  • 改变main.ts文件,使用全局注册组件(更加方便,这里参考[官方文档],有重复的,者这里自行进行删除即可(https://antdv.com/docs/vue/getting-started-cn):
import { createApp } from 'vue';
import Antd from 'ant-design-vue';
import App from './App';
import 'ant-design-vue/dist/reset.css';const app = createApp(App);app.use(Antd).mount('#app');

在这里插入图片描述

然后我们随便引入一个组件来看看是否成功引入组件,这里我以按钮组件为例:

  • 引入组件库中的按钮组件:
<a-button type="primary" danger>Primary</a-button>

运行后效果如下:
在这里插入图片描述
由此可以知道Ant Design Vue组件库引入成功了。

开发规范

Vue组件中可以按照该两种不同的风格进行书写:选项式API组合式API。这里为了使项目开发过程中更加高效,所以使用了Vue3中的组合式API,而不是选项式API。

  • 这里使用组合式API进行示范,示例代码如下:
<template><div id="xxPage"></div>
</template><script setup lang="ts"></script><style scoped>
#xxPage {
}
</style>

好了,接下来正式进行前端初始化页面模板的开发。

三、页面基本信息

修改页面搜索引擎优化页面:

<!DOCTYPE html>
<html lang="">
<head><meta charset="UTF-8"><link rel="icon" href="/favicon.ico"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>智能协同云图库</title><meta name="description" content="这是一个SpringBoot + Vue3的智能协同云图库平台">
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

基础布局结构

在layouts目录下新建BasicLayout.vue文件,然后在App.vue全局页面入口文件中引入。

App.vue代码如下:

<template><div id="app"><BasicLayout /></div>
</template><script setup lang="ts">
import BasicLayout from '@/layouts/BasicLayout.vue'
</script><style scoped></style>

然后在Ant Design官网中找到Layout组件,这里以上中下结构布局来进行演示:

在这里插入图片描述
不要忘记清楚页面内的默认样式,并且移除assets目录中的main.css文件和base.css文件,防止样式污染。

BasicLayout.vue代码如下:

<template><div id="basicLayout"><a-layout style="min-height: 100vh"><a-layout-header>Header</a-layout-header><a-layout-content>Content</a-layout-content><a-layout-footer>Footer</a-layout-footer></a-layout></div>
</template><script setup lang="ts"></script>

目前样式如下:

在这里插入图片描述

全局底部栏

全局底部栏展示底部栏信息:

<a-layout-footer class="footer"><a ref="https://gitee.com/" target="_blank">智能云图库平台</a>
</a-layout-footer>

调整底部栏信息样式:

#basicLayout .footer {background: #efefef;padding: 16px;position: fixed;bottom: 0;left: 0;right: 0;text-align: center;
}

动态替换内容弄个

Vue脚手架已经帮我们引入了Vue Router路由库,可以在router/intex.ts中进行路由配置,使得能够根据访问的页面地址找到不同的组件并进行渲染。

首先需要知道哪些内容需要动态替换,很显然肯定是中间content部分:

<a-layout-content class="content"><router-view />
</a-layout-content>

页面效果如下:
在这里插入图片描述

修改content样式,要和底部栏保持一定外边距,否则内容会被遮住如下:

#basicLayout .content {background: linear-gradient(to right, #fefefe, #fff);margin-bottom: 28px;padding: 20px;
}

全局顶部栏

在components目录中新建GlobalHeader.vue文件用于实现全局顶部栏组件。

  • 使用Ant Design的菜单组件:
    在这里插入图片描述

BasicLayout.vue文件中引入该顶部栏组件:

<a-layout-header class="header"><GlobalHeader />
</a-layout-header>

下面是引入该组件的代码:

<script setup lang="ts">
import GlobalHeader from '@/components/GlobalHeader.vue'
</script>

然后修改该顶部栏组件的样式(主要是为了清楚默认样式),代码如下:

#basicLayout .header {padding-inline: 20px;margin-bottom: 16px;color: unset;background: white;
}

修改GlobalHeader组件

  • 给该菜单组件外面套一层元素,用于控制整体的样式,代码如下:
<div class="globalHeader"><a-menu v-model:selectedKeys="current" mode="horizontal" :items="items" />
</div>
  • 然后修改菜单配置,代码如下:
<script lang="ts" setup>
import { h, ref } from 'vue'
import { HomeOutlined } from '@ant-design/icons-vue'
import { MenuProps } from 'ant-design-vue'const current = ref<string[]>(['home'])
const items = ref<MenuProps['items']>([{key: '/',icon: () => h(HomeOutlined),label: '主页',title: '主页',},{key: '/about',label: '关于',title: '关于',},{key: 'others',label: h('a', { href: 'https://www.codefather.cn', target: '_blank' }, '编程导航'),title: '编程导航',},
])
</script>
  • 接着继续完善全局顶部栏,在左侧补充网站logo(根据自己需要找一个就行)和标题:
    将找到的logo.png图片放到src/assets目录下,替换掉原本的默认Logo即可:

代码如下(其中RouterLink组件作用是支持超链接跳转(不刷新页面)):

<div id="globalHeader"><RouterLink to="/"><div class="title-bar"><img class="logo" src="../assets/logo.png" alt="logo" /><div class="title">智能协同云图库</div></div></RouterLink><a-menu v-model:selectedKeys="current" mode="horizontal" :items="items" />
</div>

css样式如下:

<style scoped>
.title-bar {display: flex;align-items: center;
}.title {color: black;font-size: 18px;margin-left: 16px;
}.logo {height: 48px;
}
</style>

目前页面效果如下:
在这里插入图片描述

  • 接着,实现右侧展示当前用户的登录状态,代码如下:
<div class="user-login-status"><a-button type="primary" href="/user/login">登录</a-button>
</div>
  • 最后一步:优化导航栏的布局,使用Ant Design的栅格组件的自适应布局(左右宽度固定,中间菜单栏自适应),代码如下:
<div id="globalHeader"><a-row :wrap="false"><a-col flex="200px"><RouterLink to="/"><div class="title-bar"><img class="logo" src="../assets/logo.png" alt="logo" /><div class="title">智能协同云图库</div></div></RouterLink></a-col><a-col flex="auto"><a-menu v-model:selectedKeys="current" mode="horizontal" :items="items" /></a-col><a-col flex="120px"><div class="user-login-status"><a-button type="primary" href="/user/login">登录</a-button></div></a-col></a-row>
</div>

最终效果如下图所示:
在这里插入图片描述

到这里,全局通用布局结束了,接下来进行路由的配置。

四、路由

现在,要实现点击不同的菜单项从而跳转到不同的页面,并实现菜单项的高亮。

在这里插入图片描述
我们可以看到router目录下index.ts文件中的routes提供了两种不同加载组件的方式:第一种方式是直接加载组件(无论是否使用组件均会加载进来);第二种方式是按需加载(懒加载,即用到哪个组件就加载哪个组件,用不到就不加载)。

路由跳转

现在我们来实现菜单项的路由跳转功能,给GlobalHeader组件的菜单组件绑定跳转事件,代码如下:

import { useRouter } from "vue-router";
const router = useRouter();// 路由跳转事件
const doMenuClick = ({ key }: { key: string }) => {router.push({path: key,});
};

html代码如下:

<a-menuv-model:selectedKeys="current"mode="horizontal":items="items"@click="doMenuClick"
/>

现在,点击对应的菜单项会显示高亮,但是页面说刷新后当前选中的菜单项并不会高亮。

代码高亮实现

代码如下:

const router = useRouter();
// 当前选中菜单
const current = ref<string[]>([]);
// 监听路由变化,更新当前选中菜单
router.afterEach((to, from, next) => {current.value = [to.path];
});

当我们进入页面的时候,current变量初始时候是没有的;由于afterEach函数,每次前往新页面时,都会把当前要前往页面的路径设置给current变量。

高亮显示原理:

  • 点击菜单时,Ant Design组件已经通过v-model 绑定current变量实现了高亮。
  • 每次刷新页面都会获取到当前的url路径,然后修改current变量的值,从而实现同步。

五、Axios请求库

前端需要获取数据时,前端需要向后端接口发送请求,由后端执行操作并响应数据给前端。这里使用第三方库Axios来发送请求。

安装请求工具库Axios(参考官方文档https://axios-http.com/docs/intro)

npm install axios

在这里插入图片描述
我们如何来使用Axios库呢?接下来看全局自定义请求。

全局自定义请求

需要自定义全局请求地址等,可以参照Axios官方文档,编写请求配置文件request.ts。包括全局接口请求地址、超时时间、自定义请求响应拦截器等。

代码如下:

import axios from 'axios'
import { message } from 'ant-design-vue'// 创建 Axios 实例
const myAxios = axios.create({baseURL: 'http://localhost:8126',timeout: 60000,withCredentials: true,
})// 全局请求拦截器
myAxios.interceptors.request.use(function (config) {// Do something before request is sentreturn config},function (error) {// Do something with request errorreturn Promise.reject(error)},
)// 全局响应拦截器
myAxios.interceptors.response.use(function (response) {const { data } = response// 未登录if (data.code === 40100) {// 不是获取用户信息的请求,并且用户目前不是已经在用户登录页面,则跳转到登录页面if (!response.request.responseURL.includes('user/get/login') &&!window.location.pathname.includes('/user/login')) {message.warning('请先登录')window.location.href = `/user/login?redirect=${window.location.href}`}}return response},function (error) {// Any status codes that falls outside the range of 2xx cause this function to trigger// Do something with response errorreturn Promise.reject(error)},
)export default myAxios

自动生成请求代码

前端请求代码这里使用OpenAPI工具自动生成(根据后端的swagger接口文档地址生成前端的请求代码),参考官方文档:https://www.npmjs.com/package/@umijs/openapi

  • 安装命令:
npm i --save-dev @umijs/openapi

然后在项目根目录中新建openapi.config.js文件,代码如下:

import { generateService } from '@umijs/openapi'generateService({requestLibPath: "import request from '@/request'",schemaPath: 'http://localhost:8126/api/v2/api-docs',serversPath: './src',
})
  • package.json的script中添加"openapi": "node openapi.config.js"
    在这里插入图片描述
    不要忘记将schemPath改为自己后端服务提供的Swagger接口文档的地址。现在执行刚刚添加的"openapi": "node openapi.config.js"即可生成可执行代码。

如下图所示:
在这里插入图片描述
之后每次后端接口发生变更时只需要重新执行生成一遍就好了。

测试请求

现在可以试着在任意页面代码中调用API:

import { healthUsingGet } from '@/api/mainController'healthUsingGet().then((res) => {console.log(res)
})

在项目后端初始化阶段,已经添加了全局跨域配置,正常情况下出现如下响应:

在这里插入图片描述
如果出现跨域问题,这是因为前端网址地址和后端请求接口地址不一致导致的。

如果后端代码无法修改或者还可以通过前端代理服务器。同时如果项目中使用Vite,内置了代理服务器。现在通过前端来解决跨域问题,修改vite.config.ts文件增加代理配置

该项目由于整合了vite打包工具,而vite默认给我们提供了一个代理服务器的配置。增加代理配置代码如下(vite.config.ts文件):

export default defineConfig({server: {proxy: {'/api': 'http://localhost:8126',}},
})

还需要修改request.ts文件

// 创建 Axios 实例
const myAxios = axios.create({baseURL: "", //本地开发环境// baseURL: 'http://localhost:8126',timeout: 60000,withCredentials: true,
})

由此,前端发送的请求域名就等同于当前URL的域名,就不会出现跨域。当我们访问到/api开头的接口时,会被代理到请求8126端口的后端服务器,从而完成请求。

六、全局状态管理

全局状态管理可以立即为多个页面要共享的数据,适合作为全局状态管理的数据比如说已登录的用户信息。

引入Pinia,最开始创建项目时vue脚手架已经引入了Pinia,所以无需再次引入了。当然如果没有引入Pinia的话可以参照官方文档。

定义状态

src/stores目录中创建useLoginUserStore.ts文件定义user模块:

代码如下:

import { defineStore } from "pinia";
import { ref } from "vue";export const useLoginUserStore = defineStore("loginUser", () => {const loginUser = ref<any>({userName: "未登录",});async function fetchLoginUser() {// todo 由于后端还没提供接口,暂时注释// const res = await getCurrentUser();// if (res.data.code === 0 && res.data.data) {//   loginUser.value = res.data.data;// }}function setLoginUser(newLoginUser: any) {loginUser.value = newLoginUser;}return { loginUser, setLoginUser, fetchLoginUser };
});

引入状态

可以直接使用store中导出的状态变量和函数,如下:
在这里插入图片描述

一般我们首次进入页面时都会获取登录用户的信息,修改App.vue文件,添加部分代码来远程获取用户数据,如下:

import { useLoginUserStore } from '@/stores/useLoginUserStore.ts'const loginUserStore = useLoginUserStore()
loginUserStore.fetchLoginUser()

接下来修改全局顶部栏组件(即GlobalHeader.vue文件),在顶部栏右侧展示用户状态,代码如下:

<div class="user-login-status"><div v-if="loginUserStore.loginUser.id">{{ loginUserStore.loginUser.userName ?? '无名' }}</div><div v-else><a-button type="primary" href="/user/login">登录</a-button></div>
</div>

测试全局状态管理

在userStore中编写测试代码

async function fetchLoginUser() {// 测试用户登录,3 秒后登录setTimeout(() => {loginUser.value = { userName: '用于展示登录用户信息', id: 1 }}, 3000)
}

最终效果:进入页面3秒钟后,顶部栏右侧会展示出登录用户信息。

在这里插入图片描述

至此,该项目的前端初始化完结散花。


http://www.ppmy.cn/news/1557419.html

相关文章

自建MD5解密平台

在这篇文档中&#xff0c;我将详细介绍如何开发一款MD5解密平台。这个平台的核心功能是生成和查询MD5彩虹表。以下是对index.php和chaxun.php文件的详细拆解和说明。 环境准备 确保开发环境的搭建&#xff0c;包括&#xff1a; PHP 7.x或更高版本MySQL 5.x或更高版本Apache或…

2025年前端面试热门题目——HTML|CSS|Javascript|TS知识

以下是对这些 HTML 面试问题的详细解答&#xff1a; 1. HTML 的 src 和 href 属性有什么区别? src (Source) 属性&#xff1a; 用于嵌入资源&#xff0c;例如图像、脚本或 iframe。加载资源时&#xff0c;当前页面的加载会暂停&#xff0c;直到资源加载完成。常用于 <img&g…

全脐点曲面当且仅当平面或者球面的一部分

S 是全脐点曲面当且仅当 S 是平面或者球面的一部分。 S_\text{ 是全脐点曲面当且仅当 }{S_\text{ 是平面或者球面的一部分。}} S 是全脐点曲面当且仅当 ​S 是平面或者球面的一部分。​ 证&#xff1a; 充分性显然&#xff0c;下证必要性。 若 r ( u , v ) r(u,v) r(u,v)是…

iClient3D for Cesium 实现限高分析

作者&#xff1a;gaogy 1、背景 随着地理信息技术的发展&#xff0c;三维地球技术逐渐成为了许多领域中的核心工具&#xff0c;尤其是在城市规划、环境监测、航空航天以及军事领域。三维地图和场景的应用正在帮助人们更加直观地理解空间数据&#xff0c;提供更高效的决策支持。…

Windows11 家庭版安装配置 Docker

1. 安装WSL WSL 是什么&#xff1a; WSL 是一个在 Windows 上运行 Linux 环境的轻量级工具&#xff0c;它可以让用户在 Windows 系统中运行 Linux 工具和应用程序。Docker 为什么需要 WSL&#xff1a; Docker 依赖 Linux 内核功能&#xff0c;WSL 2 提供了一个高性能、轻量级的…

CMake 实战练习

本文将演示如何使用 CMake 管理一个中等复杂度的项目&#xff0c;从创建项目到编译和运行的整个过程&#xff0c;涵盖了从基本配置到高级特性的实际应用。 实战内容如下&#xff1a; 创建 CMakeLists.txt 文件&#xff1a;定义项目、库、可执行文件和测试。编写源代码和测试&…

【LeetCode: 876. 链表的中间结点 + 链表】

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

3D开发工具HOOPS助力造船业加速设计与数字化转型

随着造船业对设计、高效精准建模和快速原型开发的需求不断增加&#xff0c;先进的3D技术逐渐成为推动行业创新的核心工具。Tech Soft 3D的HOOPS SDK作为行业领先的开发平台&#xff0c;已被NAPA、Herbert-ABS和三菱造船有限公司等全球造船业领导者所采用&#xff0c;帮助企业加…