vue-element-adminV4.0版本遇到的⼀些问题及解决⽅案
⽬录
⽂章⽬录
V4.0与之前版本的差异
在vue-element-admin V4.0之前的版本,根⽬录下存在2个⽂件夹:
build⽂件夹包含构建相关的build及webpack等⽂件。
config⽂件夹包含各种环境下的配置。
通常地,各种基础设置都能在这2个⽂件夹下的配置⽂件中完成。
然⽽,V4.0版本变化较⼤:
build⽂件夹保留,但其下只剩了⼀个index.js⽂件。
config⽂件夹去掉。
根⽬录下多了2种重要⽂件:.,fig.js。
其中,.为开发/⽣产环境的配置⽂件,fig.js为整个⼯程的全局配置⽂件。
修改服务端地址
要修改服务端地址,打开.env.development,这是开发环境的配置⽂件。其下有个配置是:
VUE_APP_BASE_API='/dev-api'
将该处地址修改为正确的服务端地址:
VUE_APP_BASE_API='192.168.15.98:9098/template'
即可。
服务端地址前被附加localhost:9527/
曾经⼀度排查了很久,将Mock屏蔽也不起作⽤。有两种解决⽅法:
1. 修改fig.js中的devServer,配置proxy指向服务端。
2. 从github上重新下载最新的vue-element-admin。
然⽽在采⽤这两种⽅法的同时也修改了其他的设置,且上述问题后续没有再遇到,故⽽个⼈不太确定是否是这两种解决⽅案起作⽤了。同时,不知道是否与运⾏环境为VS Code有关。
启动⼯程测试时会打开2个页⾯
每次运⾏npm run dev,会启动默认浏览器并打开2个页⾯。
解决⽅法为:
1. 打开fig.js,其中devServer.open默认为true,更改为false。
2. 打开package.json,其中scripts.dev默认为vue-cli-service serve,将其修改为:vue-cli-service serve --open。
同时访问服务端和Mock
⼀开始使⽤Mock定义了所有的接⼝。随着服务端开放部分接⼝,这部分接⼝就需要改为访问服务端。此时就需要同时访问服务端和Mock。
同时访问服务端和Mock有两种思路:
1. 使⽤同⼀个request。然后根据具体情况设置来拦截服务端接⼝或者Mock接⼝。
2. 使⽤2个request,访问服务端的request和访问Mock的request互不⼲涉。
使⽤同⼀个request
使⽤同⼀个request有2种⽅式:
1. Mock地址为VUE_APP_BASE_API,拦截服务端接⼝并将其更改为服务端地址。
2. 服务端地址为VUE_APP_BASE_API,拦截Mock接⼝并将其更改为Mock地址。
Mock地址为VUE_APP_BASE_API
默认地,VUE_APP_BASE_API = '/dev-api'。这个不需要更改。
打开fig.js,修改其devServer,添加proxy属性:
proxy:{
'/login':{
target:'192.168.15.98:/template',
changeOrigin:true,
pathRewrite:{
['^'+ v.VUE_APP_BASE_API]:''
}
}
}
更改前:localhost:9527/dev-api/login
更改后:192.168.15.98:/template/dev-api/login
服务端地址为VUE_APP_BASE_API
Mock数据都是存放在本地的,因此所有Mock接⼝是本地定义的,不需要服务端⼲涉。故⽽Mock接⼝可以添加统⼀前缀。当服务端对应接⼝开放,删掉相应Mock接⼝并修改对应访问即可。
于是将服务端地址设为VUE_APP_BASE_API,然后拦截Mock的接⼝。还要修改/mock/mock-server.js中的responseFake,其中⽤到的url更改为Mock的地址。
理论来说与前⼀种⽅式相同。但实际会遇到跨域的问题。
⾸先明确本机是localhost。
前⼀种⽅式访问的地址是本地,访问服务端接⼝时,代理将对localhost的访问转为对服务端的访问,也就是说是从localhost访问localhost,然后代理转给服务端,这样是没问题的。
然⽽这⼀种⽅式的访问的地址是服务端地址,这就意味着访问Mock端⼝时,需要代理将对服务端的访问转为对本地的访问,即从localhost 访问服务端,然后代理将服务端地址转为localhost。这样就跨域了。
不推荐使⽤此⽅式。
使⽤2个request
请求都是由/src/utils/request.js负责。因此复制⼀个request.js,改名为requestMock.js,将其中ate()时所调⽤的地址更改为Mock的地址。
然后到/src/api/下所有需要访问Mock的⽂件,将其中:
import request from '@/utils/request'
更改为:
import request from '@/utils/requestMock'
然后还要修改/mock/mock-server.js中的responseFake,其中⽤到的url更改为Mock的地址。
这样,2个request互不影响,问题解决。
⾃定义token
接收token并保存
打开 /src/store/modules/user.js,其中actions下的login()为调⽤⽤户⾃定义登录接⼝并进⾏回调处理。
在这⾥获取到的response即为服务端返回的数据。从中即可获取token值。
在下⽅会调⽤commit()和setToken()来将这个token值保存起来。
将token附加到请求的header
打开 /src/utils/request.js,有这样⼀段代码:
// request interceptor
quest.use(
config =>{
// do something before request is sent
s.token){
// let each request carry token
// ['X-Token'] is a custom headers key
// please modify it according to the actual situation
config.headers['X-Token']=getToken()
}
return config
},
error =>{
// do something with request error
console.log(error)// for debug
ject(error)
}
)
其中config.headers['X-Token'] = getToken()这⾏代码的作⽤就是取出token值并附加到header的X-Token属性中。若要更改属性名,或者在token值前附加特定的字符串,可以在这⾥进⾏修改。
另外,若需要对特定的返回code做拦截,也是在该⽂件中进⾏。
动态路由
vue-element-admin的动态路由⽅案是将所有路由都在web端写好,然后根据服务端返回的roles来决定显⽰哪些。
实际情况往往需要将路由存储在服务端,web端请求到数据后动态⽣成路由。
思路
vue-element-admin的动态路由流程为:
1. ⽤户输⼊⽤户名和密码后点击登录,调⽤login()接⼝获取token并缓存。
其代码位于 /store/user.js :
login({ commit }, userInfo){
const{ username, password }= userInfo
return new Promise((resolve, reject)=>{
login({ username: im(), password: password }).then(response =>{
const{ data }= response
commit('SET_TOKEN', ken)
ken)
resolve()
}).catch(error =>{
reject(error)
})
})
},
2. 调⽤getInfo()接⼝获取⽤户信息并缓存,其中包含roles属性。
其代码位于 /store/user.js :
getInfo({ commit, state }){
return new Promise((resolve, reject)=>{
ken).then(response =>{
const{ data }= response
if(!data){
reject('Verification failed, please Login again.')
}
const{ roles, name, avatar, introduction }= data
// roles must be a non-empty array
if(!roles || roles.length <=0){
reject('getInfo: roles must be a non-null array!')
}
commit('SET_ROLES', roles)
commit('SET_NAME', name)
commit('SET_AVATAR', avatar)
commit('SET_INTRODUCTION', introduction)
resolve(data)
}).catch(error =>{
reject(error)
})
})
}
3. 根据roles属性对本地所有的路由进⾏过滤,只保留允许roles查看的路由,挂到router中。
其代码位于 /src/permission.js :
try{
// get user info
// note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
const{ roles }=await store.dispatch('user/getInfo')
// generate accessible routes map based on roles
const accessRoutes =await store.dispatch('permission/generateRoutes', roles)
// dynamically add accessible routes
router.addRoutes(accessRoutes)
/
/ hack method to ensure that addRoutes is complete
// set the replace: true, so the navigation will not leave a history record
next({...to, replace:true})
}catch(error){
// remove token and go to login page to re-login
await store.dispatch('user/resetToken')
<(error ||'Has Error')
vue element adminnext(`/login?redirect=${to.path}`)
NProgress.done()
}
可以看到相关逻辑位于try块中。
根据此流程,可知要满⾜需求,需要更改其中的2和3两步。设登录的账户都有个roleId属性,可通过请求服务端相关接⼝并传⼊roleId来获取⼀个路由数据数组:
1. ⽤户输⼊⽤户名和密码后点击登录,调⽤login()接⼝获取token并缓存。
2. 调⽤getInfo()接⼝获取⽤户信息并缓存,其中包含roleId属性。
3. 调⽤服务端接⼝并传⼊roleId,来获取路由数据数组。
4. 根据路由数据数组来动态⽣成路由并挂到router上。
其中第3和第4步的逻辑应在 /src/permission.js 的try中实现。提供⼀段参考代码:
try{
// get user info
const{ roleId }=await store.dispatch('user/getInfo')
// 根据roleId从服务端获取addRoutes
const addRoutes =await store.dispatch('myRoute/generateRoutes',{ roleId })
// 必须设置utes后,router.addRoutes才会⽣效
utes = at(addRoutes)
// 动态添加可访问路由表。注意已有的静态路由不要设置,否则会提⽰重复
router.addRoutes(addRoutes)
// hack method to ensure that addRoutes is complete
// set the replace: true, so the navigation will not leave a history record
next({...to, replace:true})
}catch(error){
// remove token and go to login page to re-login
await store.dispatch('user/resetToken')
<(error ||'验证失败,请重新登录')
next(`/login?redirect=${to.path}`)
NProgress.done()
}
这⾥在 /src/modules/ ⽂件夹下⾃定义了myRoute.js负责路由数据的请求及获取到数据后路由结构的⽣成,并将myRoute设置到
/store/getter.js 和 /store/index.js 中。
404拦截
需要注意的⼀点是,需要将 /src/router/index.js 中constantRoutes的最后两个404路由单独导出,加载动态路由的时候,作为动态路由的⼀部分独⽴挂到动态路由的最后。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论