哈喽大家好,今天周四啦,楼主明天要正式放假了,这里先祝大家节日快乐咯,希望在家里能继续研究点儿东西吧,今天呢是 nuxt 的最后一篇,主要是对权限登陆进行研究,这一块咱们之前在说第一个项目的时候已经稍微说到了,具体的逻辑大家可以查看这篇文章《二十四║ Vuex + JWT 实现授权验证登陆》,具体的运行原理和流程,以及什么是 vuex ,在那里已经说的很清楚了,今天咱们就是主要在 nuxt 框架中使用,主要的代码的形式,理论知识比较少了,大家可以歇一歇了。这几天写了这么多,好多人可能都没看,不过没关系,继续回顾:

二七║ Nuxt 基础:框架初探》:通过 SSR 来引入 nuxt 框架,第一次接触到该框架;

二八║ Nuxt 基础:面向源码研究Nuxt.js》:通过研究 node_modules 中的源码,带领大家一步步了解 nuxt 是如何进行服务端渲染的;

二九║ Nuxt实战:异步实现数据双端渲染》:通过首页的数据加载,更加深刻的了解到 nuxt 的双端渲染,异步很重要;

 三十║ Nuxt实战:动态路由+同构》:通过首页和详情页的交互,进一步巩固 nuxt 的渲染模式和动态路由效果。

从上边大家可以看到,几乎每一篇都会说到 nuxt 这个框架的渲染模式,这个很重要,更是对 vue 的巩固。好啦,马上开始今天的讲解~

 

 

 今天呢,咱们换一种玩儿法,就是将我们的详情页给增加一个权限,首页的数据大家都可以随便看,但是详情页却不能随便看,必须要登陆,那我们就需要在我们的详情页增加一个权限,

如果 token 存在,则发送请求验证,如果不存在,直接跳转到登录页,那我们首先要添加一个登录页

 在 pages页面文件夹下,新建login 文件夹,然后添加 index.vue 登陆页面,

这一块逻辑和我们之前的很像,大家可以参考着做对比

  1. <template>
  2. <el-row type="flex" justify="center">
  3. <el-card v-if="isLogin">
  4. 欢迎:admins
  5. <br>
  6. <br>
  7. <el-button type="primary" icon="el-icon-upload" @click="loginOut">退出登录</el-button>
  8. </el-card>
  9. <el-form v-else ref="loginForm" :model="user" :rules="rules" status-icon label-width="50px">
  10. <el-form-item label="账号" prop="name">
  11. <el-input v-model="user.name"></el-input>
  12. </el-form-item>
  13. <el-form-item label="密码" prop="pass">
  14. <el-input v-model="user.pass" type="password"></el-input>
  15. </el-form-item>
  16. <el-form-item>
  17. <el-button type="primary" icon="el-icon-upload" @click="login">登录</el-button>
  18. </el-form-item>
  19. </el-form>
  20. </el-row>
  21. </template>
  22.  
  23. <script>
  24. import Vue from "vue";
  25. export default {
  26. methods: {
  27. login: function() {
  28. let that = this;
  29. that.$store.commit("saveToken", "");
  30. this.$refs.loginForm.validate(valid => {
  31. if (valid) {
  32. //发送请求登陆,这里要注意下返回数据格式,如果有问题,参考 http.js 中的 response 设置
  33. Vue.http.get("Login/GetTokenNuxt?name="+that.user.name+"&pass="+that.user.name+"").then(res => {
  34. if (res.success) {
  35. console.log("登陆成功");
  36. var token = res.token;
  37. that.$store.commit("saveToken", token);
  38. this.$notify({
  39. type: "success",
  40. message: "欢迎你," + this.user.name + "!",
  41. duration: 3000
  42. });
  43. this.$router.replace("/");
  44. }
  45. }).catch(err => {
  46. console.log("点赞失败", err);
  47. });
  48. } else {
  49. return false;
  50. }
  51. });
  52. },
  53. loginOut(){
  54. this.isLogin=false;
  55. this.$store.commit("saveToken", "");
  56. }
  57. },
  58. data() {
  59. return {
  60. isLogin:false,
  61. user: {},
  62. rules: {
  63. name: [{ required: true, message: "用户名不能为空", trigger: "blur" }],
  64. pass: [{ required: true, message: "密码不能为空", trigger: "blur" }]
  65. }
  66. };
  67. },
  68. created() {
  69. }
  70. }
  71. </script>

 

提醒:这里我用到了 elementUI ,请安装

  1. npm i element-ui -S

安装成功后,作为插件使用,如果你不是很了解,请访问官网《插 件》一章节,这里说的很清楚,我在之前的文件中也有提到。

 在 plugins/server_site 文件夹下,新增 ElementUI.js 文件,作为我们的插件

  1. import Vue from 'vue'
  2. import ElementUI from 'element-ui'
  3. Vue.use(ElementUI)

然后把这个 js 插件导入到 index.js 中,和 http.js一起注入到nuxt.config.js 中

  1. //这个是 server_site 服务端插件全部
  2. import Vue from "vue";
  3. import http from "./http.js";
  4. import "./ElementUI.js";//导入 elementUI插件
  5.  
  6. const install = function (VueClass, opts = {}) {
  7. // http method
  8. VueClass.http = http;
  9. VueClass.prototype.$http = http;
  10. };
  11. Vue.use(install);

因为我们是把服务端的插件都打包了 server_site 下的index中,所以我们以后不用每一个都注入到我们的配置文件 nuxt.config.js 中,只需要将 服务端插件 一个放进去即可,但是样式还是需要引用的

 

 

  1. import Vue from "vue";
  2. import Vuex from "vuex";
  3. Vue.use(Vuex);
  4. const store = () => new Vuex.Store({
  5. state: {
  6. isLogined: false,
  7. token: "",//这里主要是用到了 token
  8. userInfo: {
  9. name: ""
  10. },
  11. loginBoxVisible: false
  12. },
  13. mutations: {
  14. //保存 token 到 store和本地中
  15. saveToken(state, data) {
  16. state.token = data;
  17. window.localStorage.setItem("Token", data);
  18. },
  19. changeLoginState (state, isLogined) {
  20. state.isLogined = isLogined;
  21. },
  22. changeLoginBoxVisible (state, visible) {
  23. state.loginBoxVisible = visible;
  24. },
  25. updateUserInfo (state, userInfo) {
  26. state.userInfo = userInfo;
  27. }
  28. },
  29. actions: {
  30. initUser ({ state, commit }) {
  31. const user = JSON.parse(localStorage.getItem("userInfo"));
  32. if (user) {
  33. state.userInfo = user;
  34. commit("changeLoginState", true);
  35. }
  36. }
  37. }
  38. });
  39. export default store;

 

 大家一定还记得这个图片,这个是我们之前讲到的 nuxt 的执行流程图,这里说下 fetch()

fetch 方法用于在渲染页面前填充应用的状态树(store)数据, 与 asyncData 方法类似,不同的是它不会设置组件的数据。

如果页面组件设置了 fetch 方法,它会在组件每次加载前被调用(在服务端或切换至目标路由之前)。

 

我们可以利用该方法,获取 状态树 中的 token 信息,并做处理,在昨天的基础上,我们只对 fetch() 方法,简单修改

  1. <script>
  2. import Vue from "vue";
  3. export default {
  4. layout: "blog",
  5. async asyncData ({ params, error }) {
  6. // 获取文章详情
  7. let data = {};
  8. try {
  9. data = await Vue.http.get(`blog/${params.id}`);
  10. return {
  11. data: data
  12. };
  13. } catch (e) {
  14. //error({ statusCode: 404, message: "出错啦" });
  15. }
  16. },
  17. //在这里进行判断 token
  18. fetch ({ store, redirect }) {
  19. if (!(store.state.token&&store.state.token.length>=128)) {
  20. //跳转登录页
  21. return redirect('/login')
  22. }
  23. },
  24. data () {
  25. return {
  26. comments: []
  27. };
  28. },
  29. head () {
  30. return {
  31. title: `${this.data.btitle}`,
  32. meta: [
  33. {
  34. name: "description",
  35. content: this.data.btitle
  36. }
  37. ]
  38. };
  39. }
  40. };
  41. </script>

 

  1. // http.interceptors.request.use((data, headers) => {
  2. // return data;
  3. // });
  4. //http request 拦截器
  5. http.interceptors.request.use(
  6. config => {
  7. //注意,首次服务端渲染的时候,还没有出现 DOM,所以找不到 windows 对象,这里用 try 处理掉了
  8. try {
  9. if (window.localStorage.Token&&window.localStorage.Token.length>=128) {//store.state.token 获取不到值
  10. config.headers.Authorization = window.localStorage.Token;
  11. }
  12. }catch (e) {
  13. }
  14. return config;
  15. },
  16. err => {
  17. return Promise.reject(err);
  18. }
  19. );

 

这里我们就已经限制了详情页,需要登陆才能查看,其实这一块逻辑我们可以单拿出来放到中间件 middleware 里来使用,效果会更好,这里举个栗子:路由鉴权

提醒: 因为我们用的是 store 判断的是否登陆,但是如果刷新页面,我们用的是 服务端渲染,所以 store 会被更新掉,也就是为空了,大家可以用两个办法处理
1、用 localStorage 来判断是否存在token;

2、每次服务端渲染,需要更新状态树 store 中的 token;

 

 

 今天的讲解比较简单,主要是验证逻辑我们之前也已经提到了,在我们系列的 24 篇中,本文只是简单的将其搬到我们的 nuxt 框架中来,只不过中间还是会有一些小问题大家需要注意:

1、插件 plugins 的使用很重要,2、基于 axios 的 http 封装,我只是写了简单的一个 demo,复杂的大家可以找一些大的项目框架,自行研究研究;3、路由机制也是需要留心的一个小知识点,虽然不需要我们配置了,不过还是要了解内部结构。

好啦,nuxt 基本教程这里就说这么多吧,祝大家在大长假里开开森森哒~

 

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

版权声明:本文为laozhang-is-phi原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/laozhang-is-phi/p/9713219.html