vueSSR: 從0到1構建vueSSR項目 --- vuex的配置(數據預取)

vuex的相關配置

上一章做了node以及vue-cli3的配置,今天就來做vuex的部分。
先打開官方文檔-數據預取和狀態

看完之後,發現大致的邏輯就是
利用mixin,攔截頁面渲染完成之前,查看當前實例是否含有'asyncData'函數(由你創建以及任意名稱),
如果含有就進行調用,並且傳入你需要的對象比如(store,route)

例子

// pages/vuex/index.js
export default {
    name: "vuex",
    asyncData({
        store,
        route
    }) {
        // 觸發 action 後,會返回 Promise
        return store.dispatch('fetchItem', route.path)
    },
    computed: {
        // 從 store 的 state 對象中的獲取 item。
        item() {
            return this.$store.state.items[this.$route.path]
        }
    }
}


//mixin

import Vue from 'vue';
Vue.mixin({
    beforeMount() {
        const {
            asyncData
        } = this.$options
        if (asyncData) {
            this.dataPromise = asyncData({
                store: this.$store,
                route: this.$route
            })
        }
    }
})

上面只是個大概的示例,下面開始正式來做吧。

先創建一些文件
    src/store.config.js  跟router.config.js 一樣,在服務端運行避免狀態單例
    src/pages/store/all.js 全局公共模塊
//  src/pages/store/all.js
    const all = {
        //開啓命名空間
        namespaced: true,
        //ssr注意事項 state 必須爲函數
        state: () => ({
            count:0
        }),
        mutations: {
            inc: state => state.count++
        },
        actions: {
            inc: ({ commit }) => commit('inc')
        }
    }
    export default all;

vuex 模塊

all 單獨一個全局模塊
如果home有自己的數據,那麼就在home下 惰性註冊模塊
但是記得頁面銷燬時,也一定要銷燬模塊!!!
因爲當多次訪問路由時,可以避免在客戶端重複註冊模塊。
如果想只有個別幾個路由共用一個模塊,
可以在all裏面進行模塊嵌套,或者將這個幾個頁面歸納到一個父級路由下 ,在父級實例進行模塊惰性註冊。

// home/index.js
import all from '../store/all.js';
export default {
    name: 'home',
    computed:{
        count(){
            return this.$store.state.all.count
        }
    },
    asyncData({ store}){
        store.registerModule('all',all);
        return store.dispatch('all/inc')
    },
    data() {
        return {
            activeIndex2: '1',
            show:false,
            nav:[
                {
                    path:'/home/vue',
                    name:'vue'
                },
                {
                    path:'/home/vuex',
                    name:'vue-vuex'
                },
                {
                    path:'/home/vueCli3',
                    name:'vue-cli3'
                },
                {
                    path:'/home/vueSSR',
                    name:'vue ssr'
                }
            ]
        };
    },
    watch:{
        $route:function(){
            if(this.show){
                this.show = false;
            }
            //切換路由時,進行自增
            this.$store.dispatch('all/inc');
        }
    },
    mounted() {
        //做額外請求時,在mounted下進行

    },
    methods: {
        user_info(){
            this.http.post('/cms/i1/user_info').then(res=> {
                console.log(res.data);
            }).catch( error => {
                console.log(error)
            })
        }
    },
    destroyed(){
        this.$store.unregisterModule('all')
    }
}

數據預取

// store.config.js

    //store總配置
    import Vue from 'vue';
    import Vuex from 'vuex';

    Vue.use(Vuex);


    //預請求數據
    function fetchApi(id){
        //該函數是運行在node環境 所以需要加上域名
        return axios.post('http://localhost:8080/cms/i1/user_info');
    }
    //返回 Vuex實例 避免在服務端運行時的單利狀態
    export function createStore() {
        return new Vuex.Store({
            state:{
                items:{}
            },
            actions: {
                fetchItem ({commit}, id) {
                    return fetchApi(id).then(item => {
                        commit('setItem',{id, item})
                    })
                }
            },
            mutations: {
                setItem(state, {id, item}){
                    Vue.set(state.items, id, item.data)
                }
            }
        })
    }

mixin相關

在src下新建個methods 文件夾,這裏存放寫vue的全局代碼以及配置
獲取當前實例

// src/methods/index.js

import './mixin';
import Vue from 'vue';
import axios from 'axios';
Vue.prototype.http = axios;

// src/methods/mixin/index.js
    import Vue from 'vue';
    Vue.mixin({
        beforeMount() {
            const {
                asyncData
            } = this.$options;//這裏 自己打印下就知道了。就不過多解釋了
            //當前實例是否有該函數
            if (asyncData) {
               // 有就執行,並傳入相應的參數。
                asyncData({
                    store: this.$store,
                    route: this.$route
                })
            }
        }
    })

main.js 新增代碼

    import Vue from 'vue';
    Vue.config.productionTip = false;
    import VueRouter from 'vue-router';

    import App from './App.vue';
+   import './methods';
    //同步路由狀態
+   import { sync } from 'vuex-router-sync';


    import {
        createRouter
    } from './router.config.js';

+   import {
        createStore
    } from './store.config.js';

    export function createApp() {

        const router = createRouter()
        const store = createStore()
        //同步路由狀態(route state)到 store
        sync(store, router)
        const app = new Vue({
            router,
+           store,
            render: h => h(App)
        })
        return { 
            app,
            router,
+           store
        };
    }

下面更新,開發環境部署相關

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章