Vue大事件练习(保姆级教程)03

219 阅读3分钟

04-首页(二级路由)

1656346051640.png

1.1-配置二级路由

  • 细节:这个二级路由的路径不要乱写,因为我们的菜单栏是有服务器接口的。路径最好跟接口写的一致

    • 至于为什么这个菜单栏要设计成服务器接口,主要是因为这个地方设计到v-for一个特别难的不同标签渲染,到时候就知道了。(总之为了让大家学习到更加有深度的知识)

1656346583910.png

  • 1.配置二级路由: router/index.js
  • import Vue from "vue";
    import VueRouter from "vue-router";
    Vue.use(VueRouter);
    ​
    //1.导入组件
    import Register from "@/views/Register.vue";
    import Login from "@/views/Login.vue";
    import Main from "@/views/Main.vue";
    //导入二级路由
    import Home from '@/views/Home/Home.vue'
    import UserInfo from '@/views/User/UserInfo.vue'
    import UserAvatar from '@/views/User/UserAvatar.vue'
    import UserPwd from '@/views/User/UserPwd.vue'
    import ArtCate from '@/views/Article/ArtCate.vue'
    import ArtList from '@/views/Article/ArtList.vue'//2.路由规则
    const routes = [
      { path: "/register", component: Register },
      { path: "/login", component: Login },
      { path: "/", component: Main,children:[
        //二级路由配置
        { path: '/', component: Home },
        { path: '/home', component: Home },
        { path: '/user-info', component: UserInfo },
        { path: '/user-avatar', component: UserAvatar },
        { path: '/user-pwd', component: UserPwd },
        { path: '/art-cate', component: ArtCate },
        { path: '/art-list', component: ArtList }
      ] }
    ];
    ​
    //3.路由对象
    const router = new VueRouter({
      routes
    });
    ​
    export default router;
    ​
    

1.2-添加二级路由出口

  • 2.添加二级路由出口 Main.vue

1656346727163.png

  • 3.最终成品效果

1656346769472.png

05-项目token处理(vuex+axios拦截器)

1656351556098.png

1.1-使用vuex存储token

  • store/index.js
import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex)
​
export default new Vuex.Store({
  //1.state:存储数据
  state: {
    // 登录成功之后的 token 值
    token: '',
  },
  //2.mutations:更新数据
  mutations: {
    //更新 token
    updateToken(state, newToken) {
      state.token = newToken
    },
  },
  //3.actions: 异步更新数据
  actions: {
    
  },
  //4.modules:模块化state中的数据  
  modules: {
  }
})

1.2-登录成功之后将数据存入vuex

  • Login.vue

1656348487918.png

1656348763758.png

1.3-使用vuex的插件持久化vuex数据

默认情况下: vuex中的数据是存储在内存中的,只要页面一刷新就会消失

如果希望将vuex中的数据存入硬盘持久化,就需要使用vuex的插件:vuex-persistedstate

底层原理:自动将vuex中的数据用localStorage存入硬盘中

  • 1.下载插件

    • npm install --save vuex-persistedstate@3.2.1
  • 2.在vuex中配置插件

1656349010997.png

  • import Vue from 'vue'
    import Vuex from 'vuex'
    // 导入持久化插件
    import creteState from 'vuex-persistedstate'Vue.use(Vuex)
    ​
    export default new Vuex.Store({
      //配置持久化存储数据的 vuex 插件
      plugins: [creteState()],
      //1.state:存储数据
      state: {
        // 登录成功之后的 token 值
        token: '',
      },
      //2.mutations:更新数据
      mutations: {
        //更新 token
        updateToken(state, newToken) {
          state.token = newToken
        },
      },
      //3.actions: 异步更新数据
      actions: {
      },
      modules: {
      }
    })
    ​
    

1.4-使用vuex的actions存储用户信息

什么时候用vuex的actions : 当需要存储在vuex的数据需要异步获取

actions使用四个流程

(1)组件给actions发送消息: this.$store.dispatch('actions名',载荷)

(2) actions发送异步请求

(3)actions提交mutations更新

(4)mutations更新state数据

  • store/index.js
import Vue from "vue";
import Vuex from "vuex";
// 导入持久化插件
import creteState from "vuex-persistedstate";
//导入axios
import axios from 'axios'Vue.use(Vuex);
​
export default new Vuex.Store({
  //配置持久化存储数据的 vuex 插件
  plugins: [creteState()],
  //1.state:存储数据
  state: {
    // 登录成功之后的 token 值
    token: "",
    // 用户的基本信息
    userInfo: {}
  },
  //2.mutations:更新数据
  mutations: {
    //更新 token
    updateToken(state, newToken) {
      state.token = newToken;
    },
    // 更新用户基本信息
    updateUserInfo(state, obj) {
      state.userInfo = obj;
    }
  },
  //3.actions: 异步更新数据
  actions: {
    //context:当前的vuex实例对象store
    async initUserInfo(context) {
      const { data: res } = await axios.get("/my/userinfo");
      console.log(res)
      // 获取成功,调用mutations更新数据
      if (res.code === 0) {
        context.commit("updateUserInfo", res.data);
      }
    }
  },
  modules: {}
});
​
  • 登录成功之后,请求个人信息
  • Main.vue的created钩子中
  • //提交actions:异步请求用户信息
    this.$store.dispatch('initUserInfo')
    

1656349810339.png

1.5-使用axios拦截器发送token

axios拦截器作用: 在发送请求之前和响应数据之后拦截axios

应用场景 发送请求之前: 给服务器发token

响应数据之后:判断401错误,自动跳转登录页

1656351628023.png

  • main.js中配置axios拦截器

    • 细节:因为main.js中已经导入了router和store,所以在main.js中访问路由和vuex直接访问即可

      • (1)如果是在组件.vue文件中访问: this.$routerthis.$storethis.$axios

      • (2)如果是在js文件中访问 : 先使用es6模块化语法导入,然后才能使用

        • 你导入的是什么对象,就用什么对象
    • 字符串的startsWith是js原生的方法,作用是判断字符串是否以某个字符串开头

import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
​
Vue.config.productionTip = false;
​
//1.导入全局样式表
import "@/assets/global.less";
​
//2.导入 element-ui
//(1)导入+注册 组件
import ElementUI from "element-ui";
Vue.use(ElementUI);
//(2)导入css样式
import "element-ui/lib/theme-chalk/index.css";
​
//3.导入 axios
import axios from "axios";
//挂载到Vue原型中
Vue.prototype.$axios = axios;
//设置基地址
axios.defaults.baseURL = "http://big-event-vue-api-t.itheima.net";
​
// 添加请求拦截器
axios.interceptors.request.use(
  function(config) {
    //请求发送之前做点什么
    // 判断本次请求是否以 /my 开头,决定是否添加身份认证的字段
    if (config.url.startsWith("/my") && store.state.token) {
      config.headers.Authorization = store.state.token
    }
    return config;
  },
  function(error) {
    //请求错误做点什么
    return Promise.reject(error);
  }
);
​
// 响应拦截器
axios.interceptors.response.use(
  function(response) {
    // 响应成功之后做点什么
    return response;
  },
  function(error) {
    // 响应失败之后做点什么
    //判断是不是token无效导致
    if (error.response.status === 401) {
      // 1. 立即清空无效的 token
      store.commit("updateToken", "");
      // 2. 跳转到登录页面
      alert('请先登录')
      router.push("/login");
    }
    return Promise.reject(error);
  }
);
​
new Vue({
  router,
  store,
  render: h => h(App)
}).$mount("#app");
​

1.6-退出登录

1656351100764.png

  • Main.vue

    • 绑定退出登录事件

      • <el-menu-item index="2" @click="logout">
            <i class="el-icon-switch-button"></i>退出
        </el-menu-item>
        
    • 完成退出登录功能

      • 细节:这里catch可以省略, 写上了点取消浏览器不爆红。 不写的话点取消浏览器爆红。(没啥区间,看你自己强迫症程度了)- - 完成退出登录功能

      • logout() {
          this.$confirm("您确认退出登录吗?", "提示", {
            confirmButtonText: "确定",
            cancelButtonText: "取消",
            type: "warning"
          }).then(() => {
            // 1. 清空 token
            this.$store.commit("updateToken", "");
            // 2. 跳转到登录页面
            this.$router.push("/login");
          }).catch(()=>{})
        }