哈嘍你們好,今天週四啦,樓主明天要正式放假了,這裏先祝你們節日快樂咯,但願在家裏能繼續研究點兒東西吧,今天呢是 nuxt 的最後一篇,主要是對權限登陸進行研究,這一塊我們以前在說第一個項目的時候已經稍微說到了,具體的邏輯你們能夠查看這篇文章《二十四║ Vuex + JWT 實現受權驗證登陸》,具體的運行原理和流程,以及什麼是 vuex ,在那裏已經說的很清楚了,今天我們就是主要在 nuxt 框架中使用,主要的代碼的形式,理論知識比較少了,你們能夠歇一歇了。這幾天寫了這麼多,好多人可能都沒看,不過不要緊,繼續回顧:html
《二七║ Nuxt 基礎:框架初探》:經過 SSR 來引入 nuxt 框架,第一次接觸到該框架;vue
《二八║ Nuxt 基礎:面向源碼研究Nuxt.js》:經過研究 node_modules 中的源碼,帶領你們一步步瞭解 nuxt 是如何進行服務端渲染的;node
《二九║ Nuxt實戰:異步實現數據雙端渲染》:經過首頁的數據加載,更加深入的瞭解到 nuxt 的雙端渲染,異步很重要;ios
《 三十║ Nuxt實戰:動態路由+同構》:經過首頁和詳情頁的交互,進一步鞏固 nuxt 的渲染模式和動態路由效果。git
從上邊你們能夠看到,幾乎每一篇都會說到 nuxt 這個框架的渲染模式,這個很重要,更是對 vue 的鞏固。好啦,立刻開始今天的講解~github
今天呢,我們換一種玩兒法,就是將咱們的詳情頁給增長一個權限,首頁的數據你們均可以隨便看,可是詳情頁卻不能隨便看,必需要登陸,那咱們就須要在咱們的詳情頁增長一個權限,vuex
若是 token 存在,則發送請求驗證,若是不存在,直接跳轉到登陸頁,那咱們首先要添加一個登陸頁npm
在 pages頁面文件夾下,新建login 文件夾,而後添加 index.vue 登陸頁面,element-ui
這一塊邏輯和咱們以前的很像,你們能夠參考着作對比axios
<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="帳號" 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) { //發送請求登陸,這裏要注意下返回數據格式,若是有問題,參考 http.js 中的 response 設置 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("點贊失敗", 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 ,請安裝
npm i element-ui -S
安裝成功後,做爲插件使用,若是你不是很瞭解,請訪問官網《插 件》一章節,這裏說的很清楚,我在以前的文件中也有提到。
在 plugins/server_site 文件夾下,新增 ElementUI.js 文件,做爲咱們的插件
import Vue from 'vue' import ElementUI from 'element-ui' Vue.use(ElementUI)
而後把這個 js 插件導入到 index.js 中,和 http.js一塊兒注入到nuxt.config.js 中
//這個是 server_site 服務端插件所有 import Vue from "vue"; import http from "./http.js"; import "./ElementUI.js";//導入 elementUI插件 const install = function (VueClass, opts = {}) { // http method VueClass.http = http; VueClass.prototype.$http = http; }; Vue.use(install);
由於咱們是把服務端的插件都打包了 server_site 下的index中,因此咱們之後不用每個都注入到咱們的配置文件 nuxt.config.js 中,只須要將 服務端插件 一個放進去便可,可是樣式仍是須要引用的
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;
你們必定還記得這個圖片,這個是咱們以前講到的 nuxt 的執行流程圖,這裏說下 fetch()
fetch 方法用於在渲染頁面前填充應用的狀態樹(store)數據, 與 asyncData 方法相似,不一樣的是它不會設置組件的數據。
若是頁面組件設置了
fetch
方法,它會在組件每次加載前被調用(在服務端或切換至目標路由以前)。
咱們能夠利用該方法,獲取 狀態樹 中的 token 信息,並作處理,在昨天的基礎上,咱們只對 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: "出錯啦" }); } }, //在這裏進行判斷 token fetch ({ store, redirect }) { if (!(store.state.token&&store.state.token.length>=128)) { //跳轉登陸頁 return redirect('/login') } }, data () { return { comments: [] }; }, head () { return { title: `${this.data.btitle}`, meta: [ { name: "description", content: this.data.btitle } ] }; } }; </script>
// http.interceptors.request.use((data, headers) => { // return data; // }); //http request 攔截器 http.interceptors.request.use( config => { //注意,首次服務端渲染的時候,尚未出現 DOM,因此找不到 windows 對象,這裏用 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); } );
這裏咱們就已經限制了詳情頁,須要登陸才能查看,其實這一塊邏輯咱們能夠單拿出來放到中間件 middleware 裏來使用,效果會更好,這裏舉個栗子:路由鑑權
提醒: 由於咱們用的是 store 判斷的是否登陸,可是若是刷新頁面,咱們用的是 服務端渲染,因此 store 會被更新掉,也就是爲空了,你們能夠用兩個辦法處理
一、用 localStorage 來判斷是否存在token;二、每次服務端渲染,須要更新狀態樹 store 中的 token;
今天的講解比較簡單,主要是驗證邏輯咱們以前也已經提到了,在咱們系列的 24 篇中,本文只是簡單的將其搬到咱們的 nuxt 框架中來,只不過中間仍是會有一些小問題你們須要注意:
一、插件 plugins 的使用很重要,二、基於 axios 的 http 封裝,我只是寫了簡單的一個 demo,複雜的你們能夠找一些大的項目框架,自行研究研究;三、路由機制也是須要留心的一個小知識點,雖然不須要咱們配置了,不過仍是要了解內部結構。
好啦,nuxt 基本教程這裏就說這麼多吧,祝你們在大長假裏開開森森噠~