前言:
最近在開發(fā)一個后臺管理系統(tǒng),是基于vue-element-admin進行開發(fā)的,在開發(fā)過程中感受到該框架的方便同時,也感受到了面對框架所帶來的的一些局限性和依賴性。某些問題導(dǎo)致我在開發(fā)過程中耽誤了很多時間,幸好最后都一一得到解決,所以希望寫下這篇文章來進行記錄,以便后來的使用。
介紹Vue-element-admin
這是一個集成大部分功能的后臺管理系統(tǒng)框架,也就是說大多數(shù)的組件都幫我們寫好了,他是基于vue-element進行開發(fā)布局的。
所以我們使用vue-element-admin的時候可以直接使用vue-element.。
因為工作時間的原因,導(dǎo)致一些問題可能遺漏,
下面將比較分散的述說這些框架的一些使用方法和一些在項目中遇到的坑點。
1、mock和請求
在過去,我使用過easy-mock來模擬數(shù)據(jù),剛開始聽說這個框架也有模擬數(shù)據(jù)的功能,而且是基于mock的。
其實他和easy-mock的使用差不多,不過這個框架可以直接在本地文件中模擬,不需要進行線上模擬。
例如:






本地的mock請求就是這樣運行的。
它會結(jié)合我們在.env.development來判斷我們是請求模擬的數(shù)據(jù)還是線上的數(shù)據(jù)。
那么如果想切換到線上請求?
剛接觸這個框架,甚至有些不知道如何切換到線上請求,其實他這邊是設(shè)計好的,只要我們在.env.development文件中設(shè)置我們要請求的API即可
他有兩個環(huán)境,一個是開發(fā)環(huán)境和線上環(huán)境
例如:

我們可以在不同的環(huán)境設(shè)置不同的請求地址,因為dev是我們開發(fā)的時候使用的。
pro是我們打包的候使用的,所以是不會影響的。
走到這一步,也就是說VUE_APP_BASE_API保存的使我們請求的基礎(chǔ)路徑
接下來會說一下這個框架的請求封裝。講完了框架的請求機制之后,我將講述請求具體接口的方法(和本地請求基本一致)
request.js
這個文件是該框架的請求封裝的文件,也就是說我們所有的請求都是基于這個文件的。
首先,他的請求方法是使用axios.
其次,他每次的請求都會檢測有沒有token,如果有token就會攜帶token去請求,這樣做會有一個很方便的點,那就是后臺管理系統(tǒng),本來就是需要驗證身份的,也就是說我們后面的請求基本都會使用到token,這里他已經(jīng)幫我們做好了,所以就不需要每次請求的時候手動添加一個token傳到后臺。
另外,
問題一??Status Code的問題
這個請求封裝有一個問題,那就是Status Code的問題。(在Network的header里面)。它和res.code有本質(zhì)的區(qū)別。

什么意思呢?
如果后臺的status Code返回的不是200,那么他的請求會直接當(dāng)成錯誤來使用,也就是說會直接跳到error中。他無法獲取后臺返回的信息。
因為用戶可能輸錯信息了,我們需要提醒他,我們需要把后臺的信息打印出來給用戶去看,這種情況就沒辦法實現(xiàn)了,因為該框架會把不是200的status Code值當(dāng)成報錯
所以,我們要和后臺溝通,不要返回status Code為其他的值,那如果是錯誤信息(例如res.code == 500),我們應(yīng)該如何處理。
在response里面處理。
注意:這里指的錯誤信息,不是調(diào)用接口發(fā)生錯誤,而是返回的res.code不是正常的200.
? ? ? ? ? ?如果調(diào)用接口失敗,他還是會跳到error中的


如果只是用戶輸入不正確的信息,后臺希望返回一些信息給用戶看,我們還是要后臺返回status Code為200,再去判斷res.code是什么狀態(tài),再去給用戶提供什么信息。

問題二??請求發(fā)送的參數(shù)格式問題
在初次使用該框架進行請求的時候,發(fā)現(xiàn)一個問題,就是請求后臺的時候,參數(shù)沒錯了,接口沒錯的情況下,后臺接受不到前端的數(shù)據(jù)。
這是我遇到的一大坑點。后來發(fā)現(xiàn)是格式不對,現(xiàn)在顯示的是處理后的格式。

當(dāng)時是引用了qs模塊來處理了發(fā)送的格式。


補充:
我們可以不通過qs模塊去處理格式。因為這樣只能針對一種數(shù)據(jù)格式。假如后臺需要其他格式,例如FormData,這樣全局的寫在請求上就會完蛋。
所以,我們可以通過在單獨的請求中處理每一種不同的格式。
第一種:假如后臺需要將參數(shù)以json格式寫入
我們只需要將要傳的參數(shù)寫成對象就可以。但是接口要直接寫成data


第二種:假如后臺需要將參數(shù)以FromData格式寫入
?接口要寫成params:data


第三種,文件下載類型的

把這些請求的坑點都幾乎過一遍之后,下面就來說說我們請求的步驟:
1、創(chuàng)建好一個js文件,設(shè)置好請求的參數(shù),url是請求的地址,他會自動拼接到基礎(chǔ)路徑上,method是請求方式,params是攜帶的參數(shù)
有三種寫法:params:data我們可以攜帶大量的參數(shù)? ? ? params:{id} 我們傳過去的就是id這個參數(shù),第三種就是不寫params,直接寫data,這樣的話他會把數(shù)據(jù)直接放到{}中,后臺有時候需要這樣的x-www格式

2、在頁面中引入文件,使用在util/require? ? 中定義好的請求函數(shù)名

3、直接使用,這里我們使用了async,其實可以不使用,就像普通函數(shù)一樣使用userList即可
這里getList只是一個普通函數(shù),userList才是請求函數(shù)

2、登錄問題
關(guān)于登錄,我也遇到了不少的坑
先說說這個框架的一個登錄流程
他進行登錄的時候,首先會調(diào)用登錄接口獲取到token值,只是獲取token值。
然后再根據(jù)token去獲取用戶的信息。
他會從用戶信息中獲取一個角色值,來判定這個角色擁有哪些路由權(quán)限,也就是這個用戶可以看到什么頁面是有這個角色值來做決定的。
問題一:后臺沒有返回role(角色值),遭到路由攔截
我當(dāng)初調(diào)用后臺給我的登錄接口,發(fā)現(xiàn)無論如何都無法登錄,因為后臺只返回了我一個token值。
該框架做了一個路由攔截,每當(dāng)他從登錄頁想跳到首頁的時候,他都會實施一個路由攔截。
判斷你有沒有token值,

如果有那么就會判斷你有沒有角色role值,如果沒有,他就會調(diào)用請求用戶的接口。去獲取用戶的信息,其中role值應(yīng)該返回在這個接口里面。如果有了角色值,他才可以根據(jù)這個角色來幫你配置路由和跳轉(zhuǎn)頁面。

所以從登錄頁跳轉(zhuǎn)到首頁,必須有角色值
因為我們后臺并不會返回角色值給我,所以之前我只能把角色值寫死。當(dāng)然,后面直接獲取后臺菜單就改了這里的判斷
我說明一下這種情況是出自什么原因。
該框架是基于前端來控制權(quán)限的,也就是前端根據(jù)后臺返回的角色值是什么來為用戶顯示怎樣的側(cè)邊欄(路由),前端就是根據(jù)這個role和動態(tài)路由對象中的meta中的role來進行匹配。如果有這個角色則顯示。這是該框架對于路由的做法。

然而我的需求有些不一樣,后臺是不會返回角色值給我的,我們的路由也不能寫死,后臺會把整個路由發(fā)送給我,我進行動態(tài)添加,也就是說后臺已經(jīng)處理了角色權(quán)限的問題,他返回的是該用戶可以看到的路由,我只需要添加就可以。

但是,問題來了,怎么添加,而且這種格式和我們合法的路由格式不太一樣。所以就要做一些另類的判斷。

我們會發(fā)現(xiàn)在登錄的時候,其實這個框架也做了動態(tài)添加路由的操作,router.addRoutes。
所以我們只要改造modules permission.js文件就可以得到我們的路由,
obj,是我們獲取用戶信息的時候,后臺返回給我們的數(shù)據(jù)
通過整理obj來獲取合法的路由格式



獲取正確的路由格式的判斷
我在判斷那里datas.componet===的都是我在前端設(shè)置好的父級菜單,因為這個框架的父級菜單的component都為layout組件,也就是就算點擊也不會跳頁面的,他是這個框架的總體框架,真正顯示內(nèi)容的是子菜單。



最終成功動態(tài)添加路由。
但是還是遇到不少坑,就是相同方法的情況下,返回錯誤。原因是component是需要和我們前端這邊配置好的,如果前端沒有這個組件,后臺那邊添加了一個數(shù)據(jù)里面的組件是我們沒有的,那么就會出現(xiàn)報錯。
第二個坑就是,其實我們把后臺的返回的路由轉(zhuǎn)為我們前端可用的路由的難點就在于componet對象這里。compoent后臺返回的是一個字符串,我們要轉(zhuǎn)成一個compoent對象,要用到_import.js文件。
3、請求時間的問題
該框架在每次請求的時候都做了一個時間的限制,也就是說超過了這個時間,無論接口返回什么信息都會以請求時長過久而取消請求。

當(dāng)然,這里的初始時長只有5000,也就是5秒,我這里設(shè)置了2分鐘。
但是還有一個問題,就是這個請求是全局的,也就是說所有請求的請求時長限制都是一樣的,現(xiàn)在有這樣一種情況,
我們希望普通的請求的請求時長限制短一點。
某些特殊的請求請求時長限制長一點。(例如:上傳圖片,上傳視頻,生成,這種非常不確定性的請求)
解決方法:
第一,另外寫一個request.js 在 請求數(shù)據(jù)的時候引用這個request.js
第二,直接使用axios調(diào)用,不走這個框架封裝的request.js
4、固釘?shù)木彺?/h1>

每次用戶登錄打開頁面,如果有使用固釘?shù)臉邮?,那么頁面將會顯示在固釘上。但是有個很尷尬的情況,那就是當(dāng)用戶退出再登錄的時候,固釘還存在,這本來是挺好的,但是如果同一個電腦,不同的用戶登錄呢,我們會發(fā)現(xiàn)第二個用戶登錄的時候依然可以看到第一個用戶留下來的頁面固釘。幸好如果第二個用戶沒有第一個用戶的頁面權(quán)限的時候,點擊固釘會跳到404.
但是這種情況對用戶的體驗非常不好,而且一定程度上會帶來一些安全性的問題,雖然問題不是很大。
一開始,我以為固釘?shù)木彺媸欠诺絣ocalStorger中,或者其他瀏覽器緩存上面,但后面發(fā)現(xiàn)并不是。他只是放到了VUEX里面,所以其實我們只要刷新頁面,數(shù)據(jù)就會消失掉。
我們只要在退出登錄的時候,把VUEX里面的數(shù)據(jù)清除掉就可以了。
補充:我們退出登錄的時候,其實必要的話可以把重定向去掉
this.$router.push('/login)

固釘?shù)挠梅ㄟ€有一個:
當(dāng)我們切換固釘時,會發(fā)現(xiàn)每一次切換固釘切換頁面時,都會重新刷新頁面,這個時候客戶可能希望你緩存前面頁面的數(shù)據(jù),別人新增數(shù)據(jù)時可能希望切換到其他頁面看一下數(shù)據(jù),你給他刷新了,這樣的體驗效果不是那么好。這個框架規(guī)定一個緩存的法則,就是我們的頁面可以設(shè)置一個name屬性,他必須和我們路由的name一直,那么頁面就會得到緩存。

必須和router.js中該頁面路由的name屬性一直
5、element的樣式
在前面我們講過,該框架是基于element開發(fā)的。其實他有全局設(shè)置了部分element的樣式,例如按鈕,固釘,菜單等。只要我們修改了他的全局樣式就可以全局改變。

我們的按鈕tyle的樣式可以在這里修改,當(dāng)然不局限按鈕的樣式

比較難修改的是菜單欄被選中時的背景顏色,因為element沒有封裝選中菜單欄時的背景顏色。
所以我們可以使用active來設(shè)置。因為菜單欄還有搜索后的樣式,所以也要設(shè)置。
以下,只是部分呈現(xiàn)(不完全):

6、坑爹的Tree組件
在項目中大多數(shù)的頁面都有一個Tree組件


但是這些數(shù)據(jù)一般都是通過后臺返回給我們的。
而后臺通常返回的數(shù)據(jù)不會這樣的格式,而是一個扁平化的數(shù)據(jù),我們要通過id,和pid來得到一個結(jié)構(gòu)化的格式。

可以使用JSON-Tree插件來將他結(jié)構(gòu)化。
https://github.com/aximario/json-tree

但是,在數(shù)據(jù)轉(zhuǎn)化的時候,可能會我們發(fā)現(xiàn)根本不行,這個時候可以把最父級的數(shù)據(jù)的pid去掉,讓后臺設(shè)置。
第二個問題。
如果我們設(shè)置了這種多選的。

我在項目中碰到了一個需求,就是用戶可以選擇多個選項。但是這里非常的坑,假設(shè),用戶選了一級1,那么一級1的所有子項都會被選中。發(fā)送的時候,會把一級1和一級1下面的子項id全部發(fā)送給后臺。
但是,如果我們沒有選一級1,而只是選一級1下面的某一個子項,那么發(fā)送的時候其實只會把選中的子項id傳過去。并不會把父級的id傳過去。但是我們的接口通常是需要我們把父級id也傳過去的,所以這就是一個坑點。幸好有了解決的方法。

坑點二
用戶選了那些選項,后臺通常都是以什么什么為true或者false來返回的,例如,一級1選中就返回true沒有選中就會返回false. 但是這個組件非??樱褪侵灰患?有一個子項被選中了,他的父級都會以true的形式返回給后臺,也就是說當(dāng)我們回顯的時候會出現(xiàn)一個問題,就算用戶在一級1里面只選中了一個子項,他回顯的時候也會把一級的所有項選中。
后面我做了一個判斷,就是把這些選中的子項的父級都選出來去掉再顯示。
因為tree組件有一個屬性,可以控制默認(rèn)顯示的值,而且去掉父級也不會有關(guān)系,因為沒有改變數(shù)據(jù),只是改變默認(rèn)顯示的數(shù)據(jù)而已,更重要的是,這個tree組件會在子集全選的時候自動選中父級,所以這就有了思路。

7、按鈕權(quán)限控制
在本次的項目中,我沒有用框架的方式。
這次權(quán)限的控制實現(xiàn)非常簡單。
首先,后臺會返回一個列表,記錄該用戶所有的按鈕權(quán)限,其實就是一個個字符串。
我們把他存到vueX里面。
我們在全局中定義一個方法。

把這個方法掛載到全局

然后在每個頁面中為那些需要權(quán)限的按鈕添加上v-if

雖然這樣做很麻煩,但是要設(shè)置按鈕級別的權(quán)限,我認(rèn)為必須是每個按鈕都要單獨設(shè)置的。
以下是官方的寫法。其實和我們的寫法差不多,只不過他是使用角色值去判斷的。

【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
相關(guān)閱讀更多精彩內(nèi)容
- 學(xué)習(xí)總結(jié)vue后臺管理系統(tǒng) 后臺頁面的權(quán)限驗證與安全性是非常重要的,可以說是一個后臺項目一開始就必須考慮和搭建的基...
- 完整項目地址:vue-element-admin系類文章一:手摸手,帶你用vue擼后臺 系列一(基礎(chǔ)篇) 前言 拖...
- iOS網(wǎng)絡(luò)架構(gòu)討論梳理整理中。。。 其實如果沒有APIManager這一層是沒法使用delegate的,畢竟多個單...
- 簡介 參考博客: 全棧開發(fā)實戰(zhàn):用Vue2+Koa1開發(fā)完整的前后端項目(更新Koa2)前置技能: 具備Vue和K...