做项目之余的反思与总结,这些都是留给我的宝贵财富!
webpack做了哪些配置,为什么要配置?
webpack.config.js和vue.config.js的区别
- webpack.config.js是webpack的配置文件,所有使用webpack作为打包工具的项目都可以使用,vue的项目可以使用,react的项目也可以使用。
- vue.config.js是vue项目的配置文件,专用于vue项目。通过vue.config.js中常用功能的配置,简化了配置工作,当然如果需要更专业的配置工作,两者在vue项目中是可以并存的。
- vue-cli3创建的时候并不会自动创建vue.config.js,因为这个是可选项,所以一般都是修改webpack的时候才会自己创建一个vue.config.js
- 再然后因为vue-cli3内部高度集成了webpack,一般来说使用者不需要再去webpack做了什么,所以没有暴露webpack的配置文件,但你依然可以创建vue.config.js去修改默认的webpack。
项目中使用了vue.config.js进行项目的配置
pc:
- 入口处做了多页面的配置
pages:{
index:{
entry: 'src/main.js',
template: 'public/index.html'
},
exportModal:{
entry: 'src/exportMoedal.js',
template: 'public/exportMoedal.html'
}
}
- 配置了configureWebpack别名依赖
configureWebpack: {
resolve:{
alias: {
"vue$": "vue/dist/vue.esm.js"
}
}
}
oa:
- 输出文件目录 地址做了修改
before: outputDir: "./dist "
after: outputDir: "./dist/icbc/eszbmp" - 配置了configureWebpack拓展项
configureWebpack: {
externals:{
"BMap": "BMap"
}
}
gbc:
// 第三方插件配置
pluginOptions: {},
// webpack相关配置
chainWebpack: (config) => {
config.resolve.alias
.set("vue$", "vue/dist/vue.esm.js")
.set("@", path.resolve(__dirname, "./src"));
},
// css相关配置
css: {
// 是否分离css(插件ExtractTextPlugin)
extract: true,
// 是否开启 CSS source maps
sourceMap: false,
// css预设器配置项
loaderOptions: {},
// 是否启用 CSS modules for all css / pre-processor files.
modules: false,
},
区分生产、测试、以及开发环境:
- 根目录下创建:.env.development/test/production等文件
- 内容如下:
#全局本地开发环境配置
NODE_ENV=production
VUE_APP_BASE_ENV=production
VUE_APP_BASE_URL=''
# 文件服务器配置,开发配置
VUE_APP_ICON_BASE_URL='http://118/6/45/147:8888'
遇到过哪些需要跨域的情况,怎么解决的
1,总行的sdk.config.js文件引入,调用总行提供的一些方法:如水印、获取用户信息、埋点等,使用jsonp的方式动态创建script文件,在main.js入口文件引入
2,本地前端和后台,开发阶段进行接口调试的时候,IP端口不一致,所以使用了vue.config.js的proxy代理的方式
3,第三方系统内嵌iframe的跨域问题: iframe的src里带上相关的登录信息(用户名、token等),内嵌的平台做了单点登录,验证通过允许跨域??
4,nginxs
遇到过哪些IE浏览器的适配问题?
- 兼容ie浏览器的时间格式化方法,ie不允许使用new Date()传入时间
// time: 2022-11-11 14:23:21
ieNewDate:(time)=>{
const day = time.split(' ')
const days = day[0].split('-')
const min = day[1].split(':')
const date = new Date()
date.setUTCFullYear(days[0], days[1] - 1, days[2])
date.setUTCHours(min[0]-8,min[1], min[2])
}
2,不支持es6的写法
main.js文件引入polyfill:import "@/babel/polyfill"
3,样式问题,兼容IE的写法
clearfix:{zoom:1}
4,IE input输入框失效的问题
解决方案:
export const IEinputClear=(e)=>{
var isBrowser = typeof window !== 'undefined'
var UA = isBrowser && window.navigator.userAgent.toLowerCase()
var isIE = UA && /msie|trident/.test(UA)
if(isIE){
let clearDom =document.getElementById(e.target.id)
let closeDom = clearDom.nextSibling
closeDom.addEventListener('click', ()=>{
clearDom.value = ""
})
}
}
遇到过哪些移动端机型适配问题,如何调试和解决的
- gbc项目中,内嵌了一个iframe页面,苹果机型底部tabbar会遮挡的问题
解决方案:区分是安卓还是ios系统,进行样式的调整 - oa项目中,不同的打开环境icon的请求前缀是不同的,需要判断pc端浏览器预览,还是微信浏览器打开(安卓用户微信内置浏览器以及ios客户端微信内置浏览器),以及是安卓还是苹果手机打开的页面。
解决方案:判断不同的平台,文件服务器配置icon地址是不同的
# 文件服务器配置,测试配置
VUE_APP_ICON_BASE_URL='http://118/6/45/147:8888'
VUE_APP_ICON_BASE_MOBILE='ICBC/ESZBMP'
如:浏览器环境 this.devIconBasePath = process.env.VUE_APP_ICON_BASE_URL
手机环境:this.devIconBasePath = process.env.VUE_APP_ICON_BASE_URL_MOBILE
sdk.config.js文件是怎么生效的,总行提供的方法有什么
import { isIos } from '@/utils';
let sdkUrl = ''
if (isIos) {
sdkUrl = '/static/js/ruahoMobileSdk_ios.min.js'
} else {
sdkUrl = '/static/js/ruahoMobileSdk_android.min.js'
}
const script = document.createElement('script')
script.type = 'text/javascript'
script.src = sdkUrl
document.getElementsByTagName('body')[0].appendChild(script)
- main.js 入口文件中引入这个文件
- 总行提供的方法有:获取用户信息、获取当前定位、添加水印、分享页面、加密预览文件、数据埋点等方法
//添加水印
try {
//eslint-disable-next-line
rh.displayWatermark()
} catch (error) {
console.log("请在行内app使用");
}
前端开发规范
1,命名规范
2,数据请求
- 对数据请求进行二次封装处理
- 请求拦截,添加统一的请求报文格式
- 响应拦截,拦截响应报文,统一管理后端返回的状态码,返回成功数据,拦截错误数据并抛出异常
登录注册的全流程,捋一捋注意点
内部员工使用的平台,默认都有权限,没有注册模块,通过身份ID验证权限。
PC:重点看路由下的promise.js文件,实现了路由拦截、权限控制以及跳转控制
OA与GBC:没有做权限管理,通过url的userId参数判断有没有登录,userId为空或者错误的话,抛出异常,首页数据列表为空(交互上应该跳转到对应的错误页,重新连接按钮)
axios二次封装,接口请求的配置这块整体回顾
具体参考以下这篇笔记:
【基础】vue项目对axios进行二次封装,request全局接口请求文件如何写? - 简书 (jianshu.com)
印象深刻的bug
GBC:
vant的vant-tree-select组件没有三级选择,只有两级选择,我们需要自己封装一个能实现省市区以及选择三级行业的联动效果
组件的实现代码如下:
项目中vuex都放了哪些内容,具体使用场景
pc:全局页面loading的显示文字、状态,设置用户信息,模块页面会放具体业务模块需要存储的束,如navheader、deptList等
oa:全局放头部导航组件的控制:如右侧是否显示分享按钮、搜索按钮等,以及右侧的点击事件控制。以及会存储全局搜索的keyword
gbc:header部分显示的企业名称、id、类别、是否关注相关的数据
GBC项目要点
项目技术选型
前端:框架是vue,UI库移动端是vant,PC端是antDesignVue,版本管理器svn和git
- 一是考虑到团队里的成员的技术储备,基本上都会vue,无需额外的学习成本
- 二是考虑到项目匹配度,
- 三是vue框架本身是轻量级,有中文社区和中文文档,有丰富的生态环境和组件支持,易学易上手
- 最后也是工商银行总行的要求,他们团队使用的是vue框架,技术上倾向于保持上下一致。
后台:框架springboot,微服务,docker容器化部署,中间件用的是tomcat,前端的静态服务器、软负载均衡和解决跨域、代理用的nginx,Jenkins自动化部署工具,缓存使用redis。数据库orecal、MySQL
- springboot业界技术主流,生态丰富
- docker容器化部署避免环境问题,解决环境差异造成的异常以及运维痛点
- Jenkins解决运维成本,自动化打包推到镜像仓库,以及部署到生产环境
路由配置以及权限验证拦截
目前的router模块结构如下:
index.js是主路由模块入口,包含以下内容:
- 引入vue和vueRouter
- 引入各种项目路由子模块以及layout页面基础结构
- 引入页面进度条以及相关配置
- 导航守卫以及后卫的相关设置
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import creditMesure from './modules/creditMesure'
import mainLayout from '@/views/layout/mainLayout'
// 页面进度条相关配置
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
NProgress.configure({easing:'ease', speed: 500, showSpinner: false})
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
},
{
path: '/main-layout',
name: 'main-layout',
component: mainLayout,
meta: {
title: '项目首页'
},
children: [
...creditMesure,
]
},
{
path: '*',
name: '404',
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue'),
mata:{
title: '404'
}
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
router.beforeEach((to,from,next)=>{
NProgress.start()
window.scrollTo(0,0)
next()
})
router.afterEach((to)=>{
NProgress.done()
document.title = to.meta.title || 'my project'
})
export default router
promise.js文件主要配置了路由拦截,控制权限,跳转控制
/**
* 路由拦截 控制权限 跳转控制
*/
// 引入配置
import router from './index'
import { getUrlParams } from '@/utils'
// 页面进度条相关配置
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
NProgress.configure({easing:'ease', speed: 500, showSpinner: false})
// 路由拦截
router.beforeEach(async (to, from, next) => {
NProgress.start()
// 去登录页面直接登陆
if(to.path === '/to-login' || to.path === '/to-login-new'){
next()
return
}
// 异步操作 必须登录成功才能继续下一步
const user_is_login = sessionStorage.getItem('user_is_login')
if(!user_is_login){
// 调用登录接口,成功后存储用户信息
await login({loginType:1}).then((res)=>{
sessionStorage.setItem('user_is_login', 'ok')
if(res.status === 'I0000'){
sessionStorage.setItem('userInfo', JSON.stringify(res.data.userInfo))
}
})
}
// 解决next重定向后无限循环的问题
const ph = sessionStorage.setItem("login_redirect_path")
const login_redirect_path = ph?ph.split('?'):ph
if(login_redirect_path && login_redirect_path[0] == to.path){
next()
}
//获取用户信息
if(!sessionStorage.getItem('global_user_info')){
// 重新初始化登录
}
// 定向跳转
if(userInfo && userInfo!== 'null'){
await getPath().then(res=>{
sessionStorage.setItem('login_redirect_path', `/${res.data.url}`)
next(`/${res.data.url}`)
}).catch((e)=>{
next(`/home`)
}).finally(()=>{
NProgress.done()
})
return
}
next()
})
//跳转成功后的设置
router.afterEach(to=>{
document.title = to.meta.title || 'ICBC'
NProgress.done()
})
export default router
token在项目中的使用,以及过期时间如何处理
只有PC平台引入token来辅助登录的验证
- 路由promise文件中,异步操作,登录成功后存储用户信息以及token
- 在公共请求头的部分带上了session里存储的token信息
- 在二次封装axios的request文件中,请求头加上了token信息
// token设置
config.headers["token"] = sessionStorage.getItem("dse_sessionId") || getUrlParams("dse_sessionId") - 过期时间由后台设置,目前是30分钟有效期,每次请求数据都会带上之前登录成功存储的token, 由后台校验,如果超时后台会返回"token过期请重新登录“,前台request文件在响应拦截模块接收到这个异常状态码,会首先清除session里的token数据,其次跳转到登录页,让用户重新登录。
分行经营管理平台设计的项目背景:
之前是各做各的,部门之间没有联动,常用的功能没有得到沉淀,原来的交互体验也不友好。技术栈也比较陈旧。设计它是希望能够处理业务之外,也想做成指导业务,决策支持的仪表盘,适合各级领导的使用。针对平时对办公时遇到的问题做了一些优化,也结合了领导的指导意见。