vuex
的簡單使用vue-router
嵌套路由vuex
本地持久化npm install vuex --save
//先切換到/client
目錄下npm install --save vuex-persist
//先切換到/client
目錄下本身能實現佈局的同窗能夠掠過"佈局"這部份內容,幾乎全是貼的代碼。css
首頁與登陸頁面沒有公用結構,考慮使用同級路由。
首頁爲上下結構,能夠考慮el-container
、el-header
、el-main
佈局。
配置頁面與首頁公用導航欄,只是將el-main
內分左右兩部分,考慮使用嵌套路由。
配置頁面將el-main
分左右兩部分,考慮el-container
、el-aside
、el-main
佈局。
html
// 更新文件: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決定子組件渲染位置(替換父組件中的<router-view>) { 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
控制組件的渲染的層級位置vue
router-view
router-view
path
控制路由跳轉的路徑webpack
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 <template> <el-container class="page-container"> <el-header class="page-header"> <div class="page-brand" @click="backToHome"> <figure class="page-logo-wrap"> <img class="page-logo" src="../../assets/logo.png" alt=""> </figure> <h2 class="page-title">Vue</h2> </div> <div class="page-controls-wrap"> <el-dropdown @command="handleDropdown"> <span class="el-dropdown-link"> <i class="el-icon-setting"></i> </span> <el-dropdown-menu slot="dropdown"> <el-dropdown-item disabled>用戶信息</el-dropdown-item> <el-dropdown-item command='backstage'>後臺管理</el-dropdown-item> <el-dropdown-item command='logout'>登出</el-dropdown-item> </el-dropdown-menu> </el-dropdown> </div> </el-header> <el-main class="page-main"> <router-view/> </el-main> </el-container> </template> <script> export default { methods: { backToHome () { this.$router.push({ path: '/home' }) }, async logout () { this.$router.push('/') }, navigateToBackstage () { this.$router.push({ path: '/backstage' }) }, handleDropdown (command) { this['dropdownStrategies'][command]() } }, data () { return { activeIndex: '1', dropdownStrategies: { 'backstage': this.navigateToBackstage, 'logout': this.logout } } } } </script> <style lang="scss" scoped> @import '~@/stylesheets/layout.scss'; .page-container { height: 100%; } .page-header { @include flex($item: center, $content: space-between); background: #fff; border-bottom: 1px solid #eaeaea; .page-brand { @include flex($item: center, $content: space-between); cursor: pointer; .page-logo-wrap { width: 46px; height: 46px; .page-logo { max-width: 100%; } } } .page-menu { flex: 1; background: transparent; border: 0; } } </style>
@import '~@/stylesheets/layout.scss';
以~
爲前綴,樣式能夠使用webpack
配置的alias
。// 新建文件:client/src/views/homePage/index.vue <template> <div>Home</div> </template>
// 新建文件:client/src/views/backstage/index.vue <template> <el-container class="backstage-container"> <el-aside class="backstage-aside"> <el-menu default-active="1" class="backstage-menu" :router="true" :unique-opened="true"> <el-menu-item index="1" :route="{ path: '/backstage/person' }"> <template slot="title"> <i class="el-icon-location"></i> <span>我的設置</span> </template> </el-menu-item> <el-menu-item index="2" :route="{ path: '/backstage/approve' }"> <i class="el-icon-document"></i> <span slot="title">審批</span> </el-menu-item> </el-menu> </el-aside> <el-main class="backstage-main"> <router-view /> </el-main> </el-container> </template> <style lang="scss" scoped> .backstage-container { height: 100%; .backstage-menu { height: 100%; overflow-y: auto; } .backstage-main { margin-left: 20px; background: #fff; } } </style>
el-menu
的:router="true"
配置 & el-menu-item
的:route="<路由配置對象>"
能夠直接實現菜單跳轉。// 新建文件:client/src/views/approve-panel/index.vue <template> <div>Approve</div> </template>
// 新建文件:client/src/views/personal-panel/index.vue <template> <div>Person</div> </template>
最終展現效果
git
多個組件公用用戶信息,將登陸用戶信息存儲,取代下方圖片中的用戶信息(alias
> account
)
github
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: '<App/>' })
// 存儲狀態 // 更新文件: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 ... <template> ... <!-- <el-dropdown-item disabled>用戶信息</el-dropdown-item> --> <el-dropdown-item disabled>{{user}}</el-dropdown-item> ... </template> ... <script> ... computed: { user () { if (this.$store.state.loginer) { const { account, alias } = this.$store.state.loginer return alias || account } } } ... </script> ...
// 更新文件:client/src/views/layout/index.vue async logout () { this.$router.push('/') this.$store.commit('resetVuex') },
若不清除狀態,直接進入/home
,會發現,用戶信息仍存在。
若下次登陸,用戶信息比上次少,甚至沒有,會有部分/所有用戶信息沒有被覆蓋。web
頁面刷新,狀態會被清空,能夠對狀態進行本地持久化處理vue-router
// 更新文件: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] //新增 })
高頻率更新的數據,並不建議持久化處理vuex
// 登出時,須要清除本地化 // 更新文件:client/src/views/layout/index.vue ... async logout () { this.$router.push('/') await localStorage.clear() this.$store.commit('resetVuex') }, ...