緣起
哈嘍大家好,今天周四啦瞻佛,樓主明天要正式放假了,這里先祝大家節(jié)日快樂咯娇钱,希望在家里能繼續(xù)研究點(diǎn)兒東西吧伤柄,今天呢是 nuxt 的最后一篇,主要是對(duì)權(quán)限登陸進(jìn)行研究文搂,這一塊咱們之前在說第一個(gè)項(xiàng)目的時(shí)候已經(jīng)稍微說到了适刀,具體的邏輯大家可以查看這篇文章《二十四║ Vuex + JWT 實(shí)現(xiàn)授權(quán)驗(yàn)證登陸》,具體的運(yùn)行原理和流程细疚,以及什么是 vuex 蔗彤,在那里已經(jīng)說的很清楚了,今天咱們就是主要在 nuxt 框架中使用疯兼,主要的代碼的形式然遏,理論知識(shí)比較少了,大家可以歇一歇了吧彪。這幾天寫了這么多待侵,好多人可能都沒看,不過沒關(guān)系姨裸,繼續(xù)回顧:
《二七║ Nuxt 基礎(chǔ):框架初探》:通過 SSR 來引入 nuxt 框架秧倾,第一次接觸到該框架;
《二八║ Nuxt 基礎(chǔ):面向源碼研究Nuxt.js》:通過研究 node_modules 中的源碼傀缩,帶領(lǐng)大家一步步了解 nuxt 是如何進(jìn)行服務(wù)端渲染的那先;
《二九║ Nuxt實(shí)戰(zhàn):異步實(shí)現(xiàn)數(shù)據(jù)雙端渲染》:通過首頁的數(shù)據(jù)加載,更加深刻的了解到 nuxt 的雙端渲染赡艰,異步很重要售淡;
《 三十║ Nuxt實(shí)戰(zhàn):動(dòng)態(tài)路由+同構(gòu)》:通過首頁和詳情頁的交互,進(jìn)一步鞏固 nuxt 的渲染模式和動(dòng)態(tài)路由效果慷垮。
從上邊大家可以看到揖闸,幾乎每一篇都會(huì)說到 nuxt 這個(gè)框架的渲染模式,這個(gè)很重要料身,更是對(duì) vue 的鞏固汤纸。好啦,馬上開始今天的講解~
零芹血、今天要完成橙色的部分
為詳情頁增加權(quán)限驗(yàn)證
今天呢贮泞,咱們換一種玩兒法楞慈,就是將我們的詳情頁給增加一個(gè)權(quán)限,首頁的數(shù)據(jù)大家都可以隨便看隙畜,但是詳情頁卻不能隨便看抖部,必須要登陸,那我們就需要在我們的詳情頁增加一個(gè)權(quán)限议惰,
如果 token 存在,則發(fā)送請(qǐng)求驗(yàn)證乡恕,如果不存在言询,直接跳轉(zhuǎn)到登錄頁,那我們首先要添加一個(gè)登錄頁
添加登錄頁傲宜,獲取token
在 pages頁面文件夾下运杭,新建login 文件夾,然后添加 index.vue 登陸頁面函卒,
這一塊邏輯和我們之前的很像辆憔,大家可以參考著做對(duì)比
<template>
<el-row type="flex" justify="center">
<el-card v-if="isLogin"> 歡迎:admins <br>
<br>
<el-button type="primary" icon="el-icon-upload" @click="loginOut">退出登錄</el-button>
</el-card>
<el-form v-else ref="loginForm" :model="user" :rules="rules" status-icon label-width="50px">
<el-form-item label="賬號(hào)" prop="name">
<el-input v-model="user.name"></el-input>
</el-form-item>
<el-form-item label="密碼" prop="pass">
<el-input v-model="user.pass" type="password"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-upload" @click="login">登錄</el-button>
</el-form-item>
</el-form>
</el-row>
</template>
<script> import Vue from "vue";
export default {
methods: {
login: function() {
let that = this;
that.$store.commit("saveToken", ""); this.$refs.loginForm.validate(valid => { if (valid) { //發(fā)送請(qǐng)求登陸,這里要注意下返回?cái)?shù)據(jù)格式报嵌,如果有問題虱咧,參考 http.js 中的 response 設(shè)置
Vue.http.get("Login/GetTokenNuxt?name="+that.user.name+"&pass="+that.user.name+"").then(res => { if (res.success) {
console.log("登陸成功"); var token = res.token;
that.$store.commit("saveToken", token); this.$notify({
type: "success",
message: "歡迎你," + this.user.name + "!",
duration: 3000 }); this.$router.replace("/");
}
}).catch(err => {
console.log("點(diǎn)贊失敗", err);
});
} else { return false;
}
});
},
loginOut(){ this.isLogin=false; this.$store.commit("saveToken", "");
}
},
data() { return {
isLogin:false,
user: {},
rules: {
name: [{ required: true, message: "用戶名不能為空", trigger: "blur" }],
pass: [{ required: true, message: "密碼不能為空", trigger: "blur" }]
}
};
},
created() {
}
} </script>
自定義 elementUI 插件
提醒:這里我用到了 elementUI ,請(qǐng)安裝
npm i element-ui -S
安裝成功后锚国,作為插件使用腕巡,如果你不是很了解,請(qǐng)?jiān)L問官網(wǎng)《插 件》一章節(jié)血筑,這里說的很清楚绘沉,我在之前的文件中也有提到。
在 plugins/server_site 文件夾下豺总,新增 ElementUI.js 文件车伞,作為我們的插件
import Vue from 'vue' import ElementUI from 'element-ui' Vue.use(ElementUI)
然后把這個(gè) js 插件導(dǎo)入到 index.js 中,和 http.js一起注入到nuxt.config.js 中
//這個(gè)是 server_site 服務(wù)端插件全部
import Vue from "vue";
import http from "./http.js";
import "./ElementUI.js";//導(dǎo)入 elementUI插件
const install = function (VueClass, opts = {}) { // http method
VueClass.http = http;
VueClass.prototype.$http = http;
};
Vue.use(install);
因?yàn)槲覀兪前逊?wù)端的插件都打包了 server_site 下的index中喻喳,所以我們以后不用每一個(gè)都注入到我們的配置文件 nuxt.config.js 中另玖,只需要將 服務(wù)端插件 一個(gè)放進(jìn)去即可,但是樣式還是需要引用的
在 strore 文件夾中沸枯,添加 index.js 文件日矫,設(shè)置我們的store數(shù)據(jù)
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex); const store = () => new Vuex.Store({
state: {
isLogined: false,
token: "",//這里主要是用到了 token
userInfo: {
name: "" },
loginBoxVisible: false },
mutations: { //保存 token 到 store和本地中
saveToken(state, data) {
state.token = data;
window.localStorage.setItem("Token", data);
},
changeLoginState (state, isLogined) {
state.isLogined = isLogined;
},
changeLoginBoxVisible (state, visible) {
state.loginBoxVisible = visible;
},
updateUserInfo (state, userInfo) {
state.userInfo = userInfo;
}
},
actions: {
initUser ({ state, commit }) { const user = JSON.parse(localStorage.getItem("userInfo")); if (user) {
state.userInfo = user;
commit("changeLoginState", true);
}
}
}
});
export default store;
在詳情頁中增加權(quán)限驗(yàn)證
大家一定還記得這個(gè)圖片,這個(gè)是我們之前講到的 nuxt 的執(zhí)行流程圖绑榴,這里說下 fetch()
fetch 方法用于在渲染頁面前填充應(yīng)用的狀態(tài)樹(store)數(shù)據(jù)哪轿, 與 asyncData 方法類似,不同的是它不會(huì)設(shè)置組件的數(shù)據(jù)翔怎。
如果頁面組件設(shè)置了
fetch
方法窃诉,它會(huì)在組件每次加載前被調(diào)用(在服務(wù)端或切換至目標(biāo)路由之前)杨耙。
我們可以利用該方法,獲取 狀態(tài)樹 中的 token 信息飘痛,并做處理珊膜,在昨天的基礎(chǔ)上,我們只對(duì) fetch() 方法宣脉,簡單修改
<script> import Vue from "vue";
export default {
layout: "blog", async asyncData ({ params, error }) { // 獲取文章詳情
let data = {}; try {
data = await Vue.http.get(`blog/${params.id}`); return {
data: data
};
} catch (e) { //error({ statusCode: 404, message: "出錯(cuò)啦" });
}
}, //在這里進(jìn)行判斷 token
fetch ({ store, redirect }) { if (!(store.state.token&&store.state.token.length>=128)) { //跳轉(zhuǎn)登錄頁
return redirect('/login')
}
},
data () { return {
comments: []
};
},
head () { return {
title: `${this.data.btitle}`,
meta: [
{
name: "description",
content: this.data.btitle
}
]
};
}
}; </script>
最后在 http.js 中车柠,開啟 http 攔截器
// http.interceptors.request.use((data, headers) => { // return data; // }); //http request 攔截器
http.interceptors.request.use(
config => { //注意,首次服務(wù)端渲染的時(shí)候塑猖,還沒有出現(xiàn) DOM竹祷,所以找不到 windows 對(duì)象,這里用 try 處理掉了
try { if (window.localStorage.Token&&window.localStorage.Token.length>=128) {//store.state.token 獲取不到值
config.headers.Authorization = window.localStorage.Token;
}
}catch (e) {
} return config;
},
err => { return Promise.reject(err);
}
);
查看頁面羊苟,體驗(yàn)效果
這里我們就已經(jīng)限制了詳情頁塑陵,需要登陸才能查看,其實(shí)這一塊邏輯我們可以單拿出來放到中間件 middleware 里來使用蜡励,效果會(huì)更好令花,這里舉個(gè)栗子:路由鑒權(quán)
提醒: 因?yàn)槲覀冇玫氖?store 判斷的是否登陸,但是如果刷新頁面凉倚,我們用的是 服務(wù)端渲染兼都,所以 store 會(huì)被更新掉,也就是為空了占遥,大家可以用兩個(gè)辦法處理
1俯抖、用 localStorage 來判斷是否存在token;2瓦胎、每次服務(wù)端渲染芬萍,需要更新狀態(tài)樹 store 中的 token;
結(jié)語
今天的講解比較簡單搔啊,主要是驗(yàn)證邏輯我們之前也已經(jīng)提到了柬祠,在我們系列的 24 篇中,本文只是簡單的將其搬到我們的 nuxt 框架中來负芋,只不過中間還是會(huì)有一些小問題大家需要注意:
1漫蛔、插件 plugins 的使用很重要,2旧蛾、基于 axios 的 http 封裝莽龟,我只是寫了簡單的一個(gè) demo,復(fù)雜的大家可以找一些大的項(xiàng)目框架锨天,自行研究研究毯盈;3、路由機(jī)制也是需要留心的一個(gè)小知識(shí)點(diǎn)病袄,雖然不需要我們配置了搂赋,不過還是要了解內(nèi)部結(jié)構(gòu)赘阀。
好啦,nuxt 基本教程這里就說這么多吧脑奠,祝大家在大長假里開開森森噠~