Koa & Mongoose & Vue实现前后端分离--08前端状态管理&路由嵌套

上节回顾

  • 密码加密
  • 后端参数校验
  • 中间件的使用 & 错误处理

工作内容

  • vuex的简单使用
  • vue-router嵌套路由
  • vuex本地持久化

准备工作

  • npm install vuex --save //先切换到/client目录下
  • npm install --save vuex-persist //先切换到/client目录下

布局分析

期望布局

Koa & Mongoose & Vue实现前后端分离--08前端状态管理&路由嵌套_第1张图片

自己能实现布局的同学可以掠过"布局"这部分内容,几乎全是贴的代码。

布局分析

首页与登录页面没有公用结构,考虑使用同级路由。
首页为上下结构,可以考虑el-containerel-headerel-main布局。
Koa & Mongoose & Vue实现前后端分离--08前端状态管理&路由嵌套_第2张图片

嵌套路由

// 更新文件:client/src/router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import Login from '@/views/login'
import Layout from '@/views/layout'
import HomePage from '@/views/homepage'
import BackStage from '@/views/backstage'
import PersonalPanel from '@/views/personal-panel'
import ApprovePanel from '@/views/approve-panel'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      redirect: '/login'
    },
    {
      path: '/login',
      name: 'Login',
      component: Login
    },
    {
      path: '/home',
      name: 'Layout',
      component: Layout,
      children: [  // children决定子组件渲染位置(替换父组件中的)
        {
          path: '',
          name: 'HomePage',
          component: HomePage
        },
        {
          path: '/backstage', // 绝对路径,决定跳转路径计算方式(不带前缀)
          name: 'BackStage',
          component: BackStage,
          children: [
            {
              path: '',
              name: 'personalPanel',
              component: PersonalPanel
            },
            {
              path: 'person', //相对路径,决定跳转路径计算方式(以父组件path为前缀)
              redirect: '/backstage'
            },
            {
              path: 'approve',
              name: 'approvePanel',
              component: ApprovePanel
            }
          ]
        }
      ]
    }
  ]
}
  • children控制组件的渲染的层级位置

    • 匹配哪一个router-view
    • 匹配路由配置父级组件中的router-view
  • path控制路由跳转的路径

    • 绝对路径:直接以path的值为跳转路径
    • 相对路径:需要加父级组件配置的path为前缀,才能作为跳转路径

页面设计

//新建样式重置文件:client/src/stylesheets/reset.css
// 篇幅有点大,网上找一份就好
...
//更新文件:client/src/main.js
...
import '@/stylesheets/reset.css'
...
//新建样式文件:client/src/stylesheets/layout.scss
@mixin flex($dir: row, $content: flex-start, $item: flex-start, $wrap: wrap) {
  display: flex;
  flex-direction: $dir;
  justify-content: $content;
  align-items: $item;
  flex-wrap: $wrap;
}
// 新建`/home`匹配的Layout组件:client/src/views/layout/index.vue


  • @import '~@/stylesheets/layout.scss';~为前缀,样式可以使用webpack配置的alias
// 新建文件:client/src/views/homePage/index.vue
// 新建文件:client/src/views/backstage/index.vue

  • el-menu:router="true"配置 & el-menu-item:route="<路由配置对象>"可以直接实现菜单跳转。
// 新建文件:client/src/views/approve-panel/index.vue
// 新建文件:client/src/views/personal-panel/index.vue

最终展示效果

状态管理

登录信息公用

多个组件公用用户信息,将登录用户信息存储,取代下方图片中的用户信息(alias > account
Koa & Mongoose & Vue实现前后端分离--08前端状态管理&路由嵌套_第3张图片

引入vuex

// 新建文件:client/src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)


const InitState = {
  loginer: {}
}
export default new Vuex.Store({
  state: {
    ...InitState
  },
  mutations: {
    putLoginer (state, loginer) {
      state.loginer = Object.assign(
        {},
        state.loginer,
        loginer
      )
    },
    resetVuex (state) {
      Object.assign(state, InitState)
    }
  }
})
// 更新文件:client/src/main.js
...
import store from './store'
...
new Vue({
  el: '#app',
  router,
  store, //新增
  components: { App },
  template: ''
})
// 存储状态
// 更新文件:client/src/views/login/index.vue
...
async onLogin () {
  ...
  console.log(res)
  if (res && res.code === '200') {
    this.$store.commit('putLoginer', res.data)
    this.$router.replace('/home')
  } else {
  ...
}
...
// 展示用户信息
//更新文件:client/src/views/layout/index.vue
...

...

...

登出清除状态

// 更新文件:client/src/views/layout/index.vue
    async logout () {
      this.$router.push('/')
      this.$store.commit('resetVuex')
    },

若不清除状态,直接进入/home,会发现,用户信息仍存在。
若下次登录,用户信息比上次少,甚至没有,会有部分/全部用户信息没有被覆盖。

效果展示

持久化

页面刷新,状态会被清空,可以对状态进行本地持久化处理

// 更新文件:client/src/store/index.js
...
import VuexPersistence from 'vuex-persist'//新增

Vue.use(Vuex)

const vuexLocal = new VuexPersistence({ //新增
  storage: window.localStorage
})
...
  mutations: {
    putLoginer (state, loginer) {
      state.loginer = Object.assign(
        {},
        state.loginer,
        loginer
      )
    },
    resetVuex (state) {
      Object.assign(state, InitState)
    }
  },
  plugins: [vuexLocal.plugin] //新增
})

高频率更新的数据,并不建议持久化处理

// 登出时,需要清除本地化
// 更新文件:client/src/views/layout/index.vue
...
async logout () {
  this.$router.push('/')
  await localStorage.clear()
  this.$store.commit('resetVuex')
},
...

持久化效果展示

参考文档

vuex
vuex-persist

你可能感兴趣的:(koa2,mongoose,vuex,vue.js)