经过近两个月的忙碌,一个项目也已接近收尾工作,期间遇到很多困难。为了迎合团队,在这个项目中,采用了一个我几乎陌生的vue,来解决和团队的协同性。期间也存在了许多的技术上的困难,面对完全陌生的vue-router路由模块以及陌生的pinia全局状态管理库,更加坚定了我对扩展技术能力的意愿。
说了这么多,言归正传,我想回顾和总结一下在这个项目中所遇到的问题以及我在完成任务后所积累的经验。
目录
1.项目起因
项目产生背景: ONT光猫注册人员需要通过复杂的Python代码才可以完成ONT光猫的注册,往往会的人又不是特别多,甲方项目要把这个注册工作,转换为web页面,从而方便工作人员进行ONT工作的注册,甲方希望可以同时兼容PC端和手机端,日后方便工作人员进行注册工作。
担任角色: 前端工程师(包括前端UI与测试工作)
2.技术实现与成果
2.1技术栈:
2.2技术栈存在的优势和特点:
- vue:渐进式JavaScript 框架,易学易用,性能出色,适用场景丰富的 Web 前端框架。
- vite:新一代的前端构建工具,打包速度快。
- vue-router: Vue.js 的官方路由,为 Vue.js 提供富有表现力、可配置的、方便的路由。
- pinia: 符合直觉的 Vue.js 状态管理库,易学易用。
- axios: Axios 是一个基于 promise 的 HTTP 库,安全可靠。
- Ant Design of Vue: 为 Web 应用提供了丰富的基础 UI 组件,方便快捷,开箱即用。
- yarn: 快速和高效,支持离线安装,并行化操作,跨平台和稳定性。
- less: 父子选择器的嵌套规则,支持运算和函数。
2.3组件自动注册特点:
本项目采用了vite + Ant Design of Vue 的组件自动注册的特点,以及自动注册vue相关的方法
<template>
<div>
<a-button type="primary">Primary Button</a-button>
{{ data }}
</div>
</template>
<script setup>
const data = ref('我是vue中的响应数据')
</script>
有了这个功能大大的提升了效率,也减少了代码的重复量。
2.4 Ant Design of Vue组件国际化的处理
我也是经过一段时间的开发才发现antd vue中的组件基本都是英文的,在我苦恼之际也是看到了antd vue官方提供的解决方法。
<template>
<a-config-provider :locale="locale">
<App />
</a-config-provider>
</template>
<script setup>
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
import locale from 'ant-design-vue/es/date-picker/locale/zh_CN';
});
</script>
这里我也是采用了antd vue官方提供的方法,使用他的语言包把整个根组件包裹。
想要了解其他的方法的小伙伴自行去antd vue官方查看 Ant Design Vue — An enterprise-class UI components based on Ant Design and Vue.js。
3.用户需求和界面设计
3.1用户需求:
用户希望这个b端项目可以同时兼容pc端和移动端,方便工作人员进行维护工作。
3.2界面设计PC端
界面设计上pc端采用了 侧边栏 + 导航栏 + 中间内容的形式来显示。
3.3界面设计移动端
移动端界面设计类似antd vue官方的移动端一样,判断宽度小于768px时让pc端的侧边栏进行了隐藏并提供了一个按钮让用户点击可以弹出侧边栏的功能。
4. 性能优化和封装
4.1 路由懒加载
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
path: "/",
name: "Home",
meta: {
title: '首页',
keepAlive: true,
requireAuth: true,
},
component: () => import("../views/Home.vue"),
}
]
这里也是采用了vue-router提供的懒加载方法,对里面的路由进行了懒加载。
4.2 组件按需引入
<template>
<div>
<AsyncComponent />
</div>
</template>
<script setup>
const AsyncComponent = defineAsyncComponent(() =>
import('../components/Components.vue')
)
</script>
这里也是采用了vue提供的方法让组件进行按需引入。
4.3 对axios的二次封装
import axios from 'axios';
//1. 创建axios对象
const service = axios.create({
baseURL: 'http://10.177.91.232:6666',
});
//2. 请求拦截器
service.interceptors.request.use(config => {
const tokenStore = useTokenStore()
config.headers.Authorization = token ? token : '';
return config;
}, error => {
Promise.reject(error);
});
//3. 响应拦截器
service.interceptors.response.use(response => {
//判断code码
return response.data
}, error => {
return Promise.reject(error);
});
export default service;
这里我进行了baseRUL的设置,也使用了拦截器对请求进行拦截判断token。
5.遇到的问题和解决方案
5.1后端long型数据传给前端精度丢失问题。
当时是准备写详情页面的时候,向后端发送Ajax的时候,发现数据不存在,在ApiPost中也是可以这个数据。当我和我的后端同学交流的时候,他和我说你那个传过去的long长整行ID丢失了,于是我在网上也是找到了解决方案。
我的解决方案是,使用第三方库json-bigint。
npm i json-bigint
// 或
yarn add json-bigint
在自己封装的api中
import request from '../request'
import JSONBig from 'json-bigint'
export function getUserList(params) {
return request({
url: '/user',
params,
transformResponse: [
function (data) {
// 对 data 进行任意转换处理
try {
return JSONBig.parse(data)
} catch (err) {
return data
}
}
]
})
}
在请求回来的参数中只需要遍历一遍就可以了
const getUserListFun = (userList) => {
getUserList({
...userList
}).then(res => {
res.data?.rows.forEach(item => {
item.id = item.id.toString()
})
data.value = res.data.rows
});
}
这也算是之前从来也没有遇到的问题之一吧。
5.2 Table组件中的父子通信问题,与解决方案。
在antd vue中columns里面的数组并不是使用的jsx来对表格进行添加对应的节点,而是使用的vue的插槽技术来进行添加节点,当时由于对vue的不熟悉从而使用了错误的props传递方式,这里就在暂时错误的传递方式了。
<a-table :data-source="data" :columns="columns" :locale="{ ...locale }">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'address'" type="primary">
<a-button @click="handleDelete(record.id)" type="primary">
删除
</a-button>
</template>
</template>
</a-table>
5.3 JsonWebToken验证
由于职没有做过前端的token校验,所以对于token的校验也是特别陌生,只是有一点概念,学过后端处理token校验的流程,只知道前端需要通过axios的拦截器来进行拦截请求,然后判断token值,
我的解决方案:
import axios from 'axios';
//1. 创建axios对象
const service = axios.create({
baseURL: 'http://10.177.91.232',
});
//2. 请求拦截器
service.interceptors.request.use(config => {
const tokenStore = useTokenStore()
config.headers.Authorization = token ? token : '';
return config;
}, error => {
Promise.reject(error);
});
这是拦截器中的处理,用户登录进行之前后端就会返回一个token,我们前端的只需要判断这个token与后端返回的token是否一致即可。
5.4 页面自适应问题
由于这个B端后台管理系统需要同时兼容手机端,所以如何进行兼容也是一个值得考虑的问题,项目刚开启的时候我的想法是使用css3中媒体查询@media来实现。越到后面越觉得这个东西实在是太麻烦了。于是我采用了vue3中提供的watch监听器来进行自适应。
const size = ref('large')
// 定义窗口大小变量
const windowWidth = ref(window.innerWidth)
// 添加窗口大小变化事件监听器
window.addEventListener('resize', () => {
windowWidth.value = window.innerWidth
})
// 处理窗口大小变化事件
watch(windowWidth, (newVal, oldVal) => {
if (newVal > 768) {
size.value = 'default'
} else {
size.value = 'small'
}
}, {
deep: true,
immediate: true
})
使用watch可以大大简化操作减少代码,配合antd vue的size属性也是非常的方便。
6. 团队合作与沟通
前面也是提到过我在这个项目中担任的角色是一个前端工程师。在一个前后端分离的项目中与团队进行沟通,与后端进行交接都是无法避免的。
6.1 前端的沟通与协同开发
因为是这个集体项目,前端也并不是我一个人在soio此项目,我与我的前端队友是一起进行沟通从而确定所需要使用的第三方库,沟通需要使用的vue的语法,然后就由一个人去把项目架子搭起来,提交到gitee上,之后的开发就是分模块开发,沟通自己想开发那个模块。
6.2 与后端的对接
因为是一个前后端分离的一个项目,从而需要前后端进行沟通,后端也是非常的负责任,他们提供了api的文档,以及一起确定使用apipost这种东西来对后端接口的调试。
6.3 团队会议
项目启动后每周是有一个时间会进行线下会议,刚开始的时候,不会觉得有什么,只是开发时间长了,每当开发到了瓶颈期时经过一次会议也会充满信心,这让我觉得我并不是在一个在做开发,而是 一整个团队。
总结
通过这个项目的完成,我对前端开发领域有了更深入的理解,并取得了一系列令人自豪的成果。通过使用先进的前端技术和工具,我们成功地实现了项目的目标,并为用户提供了出色的用户体验。在项目中,我克服了许多技术上的挑战,例如适应了一个几乎陌生的框架,并通过深入研究和学习,迅速掌握了它的优势和应用场景。在团队合作方面,我们保持了良好的沟通和协作,积极分享知识和经验,共同解决问题,使项目顺利进行。我深感荣幸能与这个优秀的团队合作,并对他们的专业素养和付出表示由衷的感谢。通过这个项目,我不仅获得了宝贵的技术经验,还发展了自己的沟通能力、解决问题的能力和团队合作精神。我期待将这些经验和技能应用于未来的项目,并继续不断学习和成长。感谢整个团队的支持和信任,我对项目的成功感到非常自豪,并对所取得的成果充满信心。