個人自學前端39-Vue16-後臺管理系統,登入、許可權的業務邏輯,修改UI框架樣式
後臺管理系統
後臺管理系統涉及的常見功能:
1:ui框架使用。快速佈局。
2:圖表的使用。echarts。
3:登入功能的處理。token。
4:許可權處理。非同步路由。
5:國際化處理。外掛。
一 UI框架
Vue的ui框架可以分為兩類:
1:PC端ui框架 => element-ui,iView。
2:移動端ui框架 => Vant,Vux,mint,ant-design-vue。
一個ui框架的使用涉及的問題:
1:安裝。(看官網)
2:引入。a:完全引入,b:按需引入。
element-ui是Vue的外掛,因此引入時,需要使用use處理一次。
完全引入會導致打包後體積比較大。
按需引入的體積沒有那麼大。(按需引入好一點)
3:主題修改。
4:佈局樣式layout佈局。
5:元件使用。(最重要)
6:圖示和顏色。
如何使用圖示,直接class換圖示名字即可。
所有ui框架的圖示都是字型圖示。文字的體積比圖片的小。
不同的顏色對應不同的關鍵字。例如element的藍色是primary。(所有ui通用)
二 如何看別人的專案
不是說全部程式碼都知道是怎麼回事才可以改。
永遠只關心跟自己修改功能相關的程式碼。不要看根自己修改功能無關的模組。
如何找到哪些模組檔案是自己需要修改的?
1:先找到頁面對應的標籤。(內容找不到,找標籤,標籤找不到,找父元素) (目的是找到需要修改的元件是哪個)
2:找到標籤後,通過全域性查詢,找到標籤所在的元件。
3:找到這個元件的繫結的資料。如果資料是靜態的很好處理,如果是動態的,需要順騰摸瓜慢慢找相關模組。
找表格 => userList元件 => tableData陣列 => getUserList方法 => userList.js檔案 => 找到介面。
如何找到我們需要修改的頁面對應的元件?
1:利用正專案中查詢類名。
2:如果找路由元件,路徑名就是元件名。如果找一般元件,標籤的類名就是元件名。(不一定)
如何找到請求資料的邏?
先找到資料對應的元件,再去元件內順騰摸瓜找到資料的來源。
三 登入的業務邏輯
1:什麼是token
token是一個字串。它攜帶了使用者的相關資訊。例如許可權資訊,賬號密碼等等。
token是用來實現使用者驗證的。
什麼是使用者驗證?
http協議是一種無狀態的協議。無狀態 => 無記憶.
前端後端通訊結束之後,如果發起新的請求,後端是無法知道當前的客戶端是不是之前通訊過的客戶端。
如果不做額外的處理,我們是無法實現保留登入狀態的功能的。
使用者驗證就是為了讓後端記住前端。用什麼記住?用token字串進行記憶。
token如何獲取?
登入成功後,後端會發生token給前端。
如何儲存token?
token需要通過本地儲存或者cookie儲存到瀏覽器中。方便隨時獲取傳送給伺服器。
token需要每次請求時都要傳送給後端。如何傳送?
一般會把token寫在header內(請求頭),因為head內的資訊會預設每次都發送給伺服器。
在header內配置一個 Authorizaion:token 20603038ce66e6abfd1182d3a68307929f7fdb40。
如何判斷token是不是過期了?
通過後端返回的資料判斷,例如:code是100表示過期了。是0表示沒過期。
如果token過期了,需要請求特定介面獲取新的token再存起來。
2:專案的登入邏輯需要做的事情
a:發起登入成功之後,把token儲存到cookie或者本地儲存。(在哪裡寫儲存的程式碼不固定)
b:路由守衛中判斷是否登入成功過。(判斷cookie或者本地儲存內有沒有token)
c:需要隨時保證token是最新的。要在響應攔截裡判斷token是否過期了。(通過伺服器返回的欄位判斷)
d:需要把登入成功之後獲取的使用者資料,儲存到vuex中。
<script>
// 如何通過token判斷使用者是不是已經登入過?
// 首先判斷本地儲存或者cookie中是不是已經有了對應token.
// 如果有token,繼續判斷token是不是過期了.
// 請求攔截 => 所有的請求發生之前,都會觸發use的回撥.
// use的回撥的引數config是axios請求的配置項.
// 通過config,可以在所有請求發生前,修改config.
// 一定記得return config,否則請求預設會失敗.
axios.interceptors.request.use(function (config) {
// 給所有的請求都新增token欄位.
config.headers.Authorizaion = localStorage.getItem('token');
// 在傳送請求之前做些什麼
return config;
}, function (error) {
// 對請求錯誤做些什麼
return Promise.reject(error);
});
// 響應攔截.每次資料請求拿到資料之前都會觸發響應攔截
// res引數就是伺服器返回的結果.
// 需要把res return出去.否則then接收不到伺服器返回的結果.
axios.interceptors.response.use(function (res) {
// console.log('res', res);
res.data.msg = '修改喲喲喲喲成功了';
// 在拿到資料之前做些什麼
return res;
}, function (error) {
// 對請求錯誤做些什麼
return Promise.reject(error);
});
const Login = {
template: `
<div>
<input type='text' />
<button @click='toPage'>登入</button>
</div>
`,
props: ['name'],
methods: {
toPage() {
axios.get('data.json').then(res => {
if (res.data.code === 0) {
// 獲取token並且儲存到本地。
localStorage.setItem('token', res.data.token);
// 跳轉到指定路由.
this.$router.push({ name: this.name });
}
});
}
}
}
const Home = {
template: `
<div>
<slot />
<h3>首頁</h3>
</div>
`,
}
const News = {
template: `
<div>
<slot />
<h3>新聞</h3>
<button @click='fn'>修改使用者資訊</button>
</div>
`,
methods: {
fn() {
axios({
url: 'editor.json',
methods: "GET",
data: "新修改的使用者名稱",
// 每次請求,都手動傳送token.
// headers: { Authorizaion: localStorage.getItem('token') },
}).then(res => {
console.log(res);
})
}
}
}
const Sport = {
template: `
<div>
<slot />
<h3>體育</h3>
<button @click='fn'>修改使用者頭像</button>
</div>
`,
methods: {
fn() {
axios({
url: '頭像介面',
methods: "POST",
data: "新修改的頭像",
// 每次請求,都手動傳送token.
headers: { Authorizaion: localStorage.getItem('token') },
}).then(res => {
console.log(res);
})
}
}
}
// 例項化路由
const router = new VueRouter({
// 路由元件和路由路徑的對應關係 => 路由選項
routes: [
{
path: '/home',
component: Home,
name: 'home',
meta: {
// 不需要登入
authLogin: false
}
}, {
path: '/news',
component: News,
name: 'news',
meta: {
authLogin: true
}
}, {
path: '/sport',
component: Sport,
name: 'sport',
meta: {
authLogin: true
}
}, {
path: '/login',
component: Login,
name: 'login',
meta: {
authLogin: false
},
props: true
},{
path: '/',
redirect: '/home'
}
]
});
// 全域性守衛處理 登入邏輯
router.beforeEach((to, from, next) => {
if (to.meta.authLogin) {
const token = localStorage.getItem('token');
if (token === null) {
// 重定向,並且傳遞目標路由的name
next({ name: 'login', params: { name: to.name } })
} else {
// if (token過期了) {
// next({ name: 'login', params: { name: to.name } })
// } else {
// next()
// }
next();
}
} else {
next()
}
});
const App = {
template: `
<div>
<router-view>
<router-link to='/home'>首頁</router-link>
<router-link to='/news'>新聞</router-link>
<router-link to='/sport'>體育</router-link>
</router-view>
</div>
`
};
new Vue({
render: h => h(App),
// 掛載路由
router
}).$mount('#app');
</script>
四 許可權
許可權 => 頁面的許可權(需要非同步路由),按鈕的許可權(v-if或者自定義指令實現),請求資料的許可權(請求攔截內實現)。
程式碼內,許可權是儲存在使用者資訊內的一個數組. => 怎麼知道登入之後的賬號許可權? => 使用者的登入資訊內獲取.
=> 根據使用者登入的許可權資訊,動態配置不同的routes陣列到路由例項內。
=> 如何動態設定不同頁面的路由?=> router.addRoutes
一般需要許可權的專案,配置路由時,路由選項需要分成兩個部分。
一個部分是不需要許可權的路由,例如登入路由和404路由。
另一個部分是需要許可權的路由。
在登入成功後,獲取到的使用者的許可權列表,再通過許可權列表從需要許可權的路由內篩選出需要的路由。
最後把不需要許可權的路由和經過篩選的路由合併,再通過addRoutes動態配置。
<script>
const Login = {
template: `
<div>
<input type='text' />
<button @click='toPage'>登入</button>
</div>
`,
props: ['name'],
methods: {
toPage() {
axios.get('userData.json').then(res => {
// 許可權角色
let role = res.data.role;
// 根據許可權過濾路由。
asyncRoutes = asyncRoutes.filter(item => item.meta.roles.includes(role));
// 過濾後配置動態路由.
router.addRoutes(asyncRoutes);
// 跳轉到首頁.
this.$router.push('/home');
});
}
}
}
const Home = {
template: `
<div>
<slot />
<h3>首頁</h3>
</div>
`,
}
const News = {
template: `
<div>
<slot />
<h3>新聞</h3>
</div>
`
}
const Sport = {
template: `
<div>
<slot />
<h3>體育</h3>
</div>
`,
}
const NotFound = {
template: `
<div>
<h3>404頁面,你要訪問的頁面不存在</h3>
</div>
`,
}
// 不需要許可權的路由選項.
const staticRoutes = [
{
path: '/login',
component: Login,
name: 'login'
}, {
path: '/notFound',
component: NotFound
}, {
path: '/',
redirect: '/login'
}
];
// 需要許可權的路由選項.
let asyncRoutes = [
{
path: '/home',
component: Home,
name: 'home',
meta: {
roles: ['editor', 'admin']
}
}, {
path: '/news',
component: News,
name: 'news',
meta: {
roles: ['admin']
}
}, {
path: '/sport',
component: Sport,
name: 'sport',
meta: {
roles: ['editor']
}
},
];
// 例項化路由,只配置不要許可權的路由。
// 其他頁面的路由選項,需要在登入之後,根據不同的使用者角色來動態配置.
const router = new VueRouter({ routes: staticRoutes });
const App = {
template: `
<div>
<router-view>
<router-link to='/home'>首頁</router-link>
<router-link to='/news'>新聞</router-link>
<router-link to='/sport'>體育</router-link>
</router-view>
</div>
`
};
new Vue({
render: h => h(App),
// 掛載路由
router
}).$mount('#app');
</script>
五 模擬資料
1:最簡單最笨的就是寫json檔案,自己請求。(簡單情況可以這樣做)
2:使用mock模擬資料。mock是一個外掛。
六 修改UI框架的樣式
如果ui框架的樣式需要修改,有以下幾種方式。
一,通過瀏覽器檢查,找到要修改的標籤的類名,然後再元件中寫一個優先順序更高的選擇器個覆蓋ui的預設樣式。
二,通過元件style的scoped來覆蓋修改。添加了scoped之後,還希望父元件的樣式影響子元件,還需要使用樣式穿透。
樣式穿透的三種寫法:
1. /deep/
2. >>>
3. ::v-deep
三,永遠的全部修改,只能改原始碼。也可以使用定製主題的方式修改,原始檔不會被修改。
不管是修改原始碼還是定製主題的方式,會對整個專案的元件都生效。
修改主題時,建議less-loader的版本是5.0.0.