從壹開始先後端分離 [ vue + .netcore 補程 ] 三十一║ Nuxt終篇:基於Vuex的權限驗證探究

緣起

哈嘍你們好,今天週四啦,樓主明天要正式放假了,這裏先祝你們節日快樂咯,但願在家裏能繼續研究點兒東西吧,今天呢是 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

 

零、今天要完成橙色的部分

 

1、爲詳情頁增長權限驗證

 今天呢,我們換一種玩兒法,就是將咱們的詳情頁給增長一個權限,首頁的數據你們均可以隨便看,可是詳情頁卻不能隨便看,必需要登陸,那咱們就須要在咱們的詳情頁增長一個權限,vuex

若是 token 存在,則發送請求驗證,若是不存在,直接跳轉到登陸頁,那咱們首先要添加一個登陸頁npm

一、添加登陸頁,獲取token

 在 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 

 

提醒:這裏我用到了 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 中,只須要將 服務端插件 一個放進去便可,可是樣式仍是須要引用的

 

 

三、在 strore 文件夾中,添加 index.js 文件,設置咱們的store數據

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.js 中,開啓 http 攔截器 

// 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;

 

 

2、結語 

 今天的講解比較簡單,主要是驗證邏輯咱們以前也已經提到了,在咱們系列的 24 篇中,本文只是簡單的將其搬到咱們的 nuxt 框架中來,只不過中間仍是會有一些小問題你們須要注意:

一、插件 plugins 的使用很重要,二、基於 axios 的 http 封裝,我只是寫了簡單的一個 demo,複雜的你們能夠找一些大的項目框架,自行研究研究;三、路由機制也是須要留心的一個小知識點,雖然不須要咱們配置了,不過仍是要了解內部結構。

好啦,nuxt 基本教程這裏就說這麼多吧,祝你們在大長假裏開開森森噠~

 

3、GitHub

https://github.com/anjoy8/Blog.Vue.Nuxt

相關文章
相關標籤/搜索