Laravel5與前端(三)導航和狀態管理

我的原文:https://www.hijerry.cn/p/33462.html

側邊導航

我們現在知道,單頁應用中的每一頁對應到一個vue組件,那麼總會有一些公共組件,例如導航,那這些公共組件在單頁中應該怎麼實現呢。我們先直接把導航的代碼寫出來試試。

版本1:先實現導航功能

html:

<div id="app">
    <h1>導航</h1>
    <ul class="menu">
        <li>
            <router-link to="/user">用戶管理</router-link>
        </li>
        <li>
            <router-link to="/course">課程管理</router-link>
        </li>
    </ul>
    <div>
        <h2>首頁</h2>
        <router-view></router-view>
    </div>
</div>

app.js:

import Vue from 'vue'
import VueRouter from 'vue-router'

const UserPage = () => import('./modules/User')
const CoursePage = () => import('./modules/Course')

Vue.use(VueRouter)

const routes = [
    { path: '/user', component: UserPage },
    { path: '/course', component: CoursePage }
]

const router = new VueRouter({
    base: '/',
    routes // (縮寫)相當於 routes: routes
})


const app = new Vue({
    el: '#app',
    router
});

此時已經可以通過導航來切換不同的頁面了。

我們可以發現這裏少了兩個東西:導航菜單沒有點亮、導航標題沒有根據路由變化來進行切換。

版本2:點亮菜單項

爲了方便,我們把導航單獨做成組件放在 components/particals/Sidebar.vue 文件中,把路由做成模塊放在 router 目錄下,把 導航標題 做成組件放在 components/particals/Header.vue,完成後結構如下:

.
├── app.js
├── bootstrap.js
├── components
│   ├── ExampleComponent.vue
│   └── particals
│       ├── NavHeader.vue
│       └── Sidebar.vue
├── modules
│   ├── Course.vue
│   └── User.vue
└── router
    └── index.js

此時app.js內容爲:

require('./bootstrap');

import Vue from 'vue'
import router from './router'

Vue.component('sidebar', () => import('./components/particals/Sidebar'))
Vue.component('nav-header', () => import('./components/particals/NavHeader'))

const app = new Vue({
    el: '#app',
    router
});

我們觀察生成的html頁面,發現生成的路由鏈接中,會自動的掛上一些標記:

這其實是vue-router的一個功能:https://router.vuejs.org/zh-cn/api/options.html#linkactiveclass

所以,我們只需在 app.scss 文件中添加如下代碼即可:

.menu a.router-link-active, .menu a.router-link-exact-active {
  color: #0a6cd6;
}

.menu a{
  color: #000;
}

版本3:切換標題

我們先來看看 NavHeader.vue 文件:

<template>
    <div>
        <h2 v-text="title"></h2>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                title: '首頁'
            }
        }
    }
</script>

可以看到,組件內有一個 title 變量,我們在切換路由時,如果可以改變這個變量值就好了,Prop可以做到這一點:https://cn.vuejs.org/v2/guide/components.html#Prop

我們需要把 NavHeader.vue script標籤內代碼改成:

export default {
    props: ['title']
}

spa.blade.php 前端模板文件中,傳入 title 值:

<nav-header title="首頁2"></nav-header>

現在這個值只是一個字面量,我們把它改成動態值。先修改 app.js,在裏面加上navTitle 變量:

const app = new Vue({
    el: '#app',
    data() {
        return {
            navTitle: '首頁'
        }
    },
    router
});

修改模板文件,將 title 綁定爲 navTitle 變量:

<nav-header :title="navTitle"></nav-header>

好了,在路由切換時怎麼變更標題呢?在router/index.js 中加入以下代碼:

router.beforeEach((to, from, next) => {
    if (to.fullPath == '/user') {
        this.a.app.navTitle = '用戶管理'
    } else if (to.fullPath == '/course') {
        this.a.app.navTitle = '課程管理'
    }
    next()
})

beforeEach 函數會在路由切換時觸發

vuex

在公共組件過多時,公共組件在各個狀態之間時會變得比較混亂,而vuex就是爲解決這個問題而誕生的,我們現在使用vuex來實現 導航標題 的切換。

爲了方便起見,我們將導航作爲配置項,放在 config 目錄下,並通過 name 屬性來引用頁面:

config/menu.js

export default [
    {
        text: '用戶管理',
        uri: { name: 'user'}
    }, {
        text: '課程管理',
        uri: { name: 'course'}
    }
]

同時修改 Sidebar.vue 內容爲:

<template>
    <ul class="menu">
        <li v-for="item in menus">
            <router-link :to="item.uri" v-text="item.text"></router-link>
        </li>
    </ul>
</template>

<script>
    import menu from "../../config/menu";

    export default {
        data() {
            return {
                menus: menu
            }
        }
    }
</script>

同時在定義路由時,爲他們添加導航標題(meta.title):

const routes = [
    {
        path: '/user',
        name: 'user',
        meta: { title: '導航標題:用戶管理' },
        component: () => import('../modules/User')
    },
    {
        path: '/course',
        name: 'course',
        meta: { title: '導航標題:課程管理' },
        component: () => import('../modules/Course')
    }
]

安裝

npm install vuex

使用

我們在建立 vuex/store.js 文件,用來保存一些公共的狀態:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
    state: {
        navTitle: '首頁'
    },
    mutations: {
        changeNavTitle(state, title) {
            state.navTitle = title
        }
    }
})

export default store

上述代碼定義了一個狀態 navTitle 表示導航標題,並提供了一個函數 changeNavTitle 來修改這個狀態。

app.js 中,將期引入到Vue中去:

...
import store from './vuex/store'
...
const app = new Vue({
    ...
    store
    ...
});

當然也需要修改 NavHeader.vue 讓他把狀態 navTitle顯示出來:

(記得把前端模板文件 spa.blade.php 裏面的 :title="navTitle" 去掉)

<template>
    <div>
        <h2 v-text="title"></h2>
    </div>
</template>

<script>
    export default {
        computed: {
            title() {
                return this.$store.state.navTitle
            }
        }
    }
</script>

隨路由切換

我們修改 beforeEach 函數:

...
import store from '../vuex/store'
...
router.beforeEach((to, from, next) => {
    store.commit('changeNavTitle', to.meta.title)
    next()
})
...

store.commit 函數會調用在 store.jsmutation 定義的方法,這也是官方推薦的修改狀態的方式。

意思是,你也可以使用 store.state.navTitle = to.meta.title 來直接修改狀態,但官方不推薦這麼做。

最後附上項目文件結構:

.
├── app.js
├── bootstrap.js
├── components
│   ├── ExampleComponent.vue
│   └── particals
│       ├── NavHeader.vue
│       └── Sidebar.vue
├── config
│   └── menu.js
├── modules
│   ├── Course.vue
│   └── User.vue
├── router
│   └── index.js
└── vuex
    └── store.js
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章