基于 Laravel + Vue 构建 API 驱动的 LBS 应用系列教程(九) —— 构建 Vuex 模块

栏目: 编程语言 · PHP · 发布时间: 6年前

内容简介:在上一篇教程中,我们在在Vuex 在跟踪应用程序中的数据状态方面也非常有用。如果你使用了 Vue 开发工具,就可以查看每个模块包含的数据以及如何访问它。

在上一篇教程中,我们在 resources/assets/js/api/cafe.js 文件中通过 JavaScript 的 Axios 库构建了一些调用 Laravel 后端 API 路由的方法。在这一篇教程中我们需要将从 API 接口获取的数据保存下来以便在单页面应用中使用,而这正是 Vuex 模块可以大展拳脚的地方。

Vuex 文档 中将 Vuex 定位成专为 Vue.js 应用程序开发的状态管理模式,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。听上去有点抽象,翻译过来就是可以在多个组件和页面中使用的单点数据。为什么我们需要这个?因为随着构建的应用越来越大,单页面也会变得越来越复杂,在多个地方使用数据会非常麻烦。例如,假设你有一份登录到应用的用户数据,有了 Vuex 模块之后,你无需通过用户名将用户作为参数传递到不同的组件,只需将其保存到 Vuex 模块中,然后在任何地方都可以访问这个模块来获取数据。

Vuex 在跟踪应用程序中的数据状态方面也非常有用。如果你使用了 Vue 开发工具,就可以查看每个模块包含的数据以及如何访问它。

Vuex 在一开始有点难以理解,因为这是一种全新的保存数据的方式,好在 Vuex 官方文档 非常详尽,你可以通过它们深入学习。不是所有的应用都需要 Vuex 来存储数据,但是如果你在构建一个大型的单页面应用,并且需要以更优雅地方式来处理数据,那么 Vuex 是一个不错的选择。

第一步:配置 resources/assets/js/store.js

我们之前已经创建过一个初始化的 store.js 文件,现在需要打开这个文件,并添加一些代码来实现一个初始化的数据存储器。

首先,需要在 store.js 顶部导入 Vue 和 Vuex:

/**
 * Import Vue and Vuex
 */
import Vue from 'vue'
import Vuex from 'vuex'

接下来,要告知 Vue 使用 Vuex 作为数据存储器,这将会扩展 Vue 实例具备使用 Vuex 数据存储器所需要的方法。将下面这行代码放到导入 Vue 和 Vuex 之后的地方:

/**
 * Initializes Vuex on Vue.
 */
Vue.use( Vuex )

最后,我们将会从 store.js 文件导出一个新的 Vuex 数据存储器。这样我们就可以将其应用到 Vue 实例并让所有模块在各个组件和路由中都可以访问。将下面这段代码放到 store.js 末尾:

/**
 * Export the data store.
 */
export default new Vuex.Store({
    modules: {

    }
});

这样我们就有了一个最基本的数据存储器配置,我们可以在其基础上轻松实现模块扩展。

第二步:安装 es6-promise 支持 IE 数据存储

上述配置在 IE 11 下不能正常工作,因为 IE 11 不支持 promise,需要通过 NPM 安装 es6-promise

npm install es6-promise --save-dev

然后在 resources/assets/js/store.js 文件顶部加入如下这段代码:

/**
 * Adds the promise polyfill for IE 11
 */
require('es6-promise').polyfill();

最终版本的 store.js 文件内容如下:

/*
 |-------------------------------------------------------------------------------
 | VUEX store.js
 |-------------------------------------------------------------------------------
 | Builds the data store from all of the modules for the Roast app.
 */

/**
 * Adds the promise polyfill for IE 11
 */
require('es6-promise').polyfill();

/**
 * Import Vue and Vuex
 */
import Vue from 'vue'
import Vuex from 'vuex'

/**
 * Initializes Vuex on Vue.
 */
Vue.use( Vuex )

/**
 * Export our data store.
 */
export default new Vuex.Store({
    modules: {

    }
});

第三步:新增数据存储器到 Vue 实例

现在数据存储器已经构建好了,需要将其添加到 Vue 中,Vue 实例位于 resources/assets/js/app.js ,打开该文件,在

import router from './routes.js'`)

之后添加如下这行代码:

import store from './store.js'

这将会引入我们上几步创建的数据存储器,接下来,我们需要通过数据存储器来扩展 Vue 实例:

new Vue({
    router,
    store
}).$mount('#app');

现在我们就可以在应用中使用整个 Vue 全家桶了!下面我们将新增一些模块并使其可以正常工作。

第四步:新增 Vuex 模块 cafes.js

首先需要在 resources/assets/js/modules 目录下创建一个名为 cafes.js 的文件,我们将在这个文件中管理所有的咖啡店数据,然后在整个应用中使用这些数据。从这里,也可以看到单页面应用的优点:一次加载页面,将数据存储到 Vuex 模块,到处使用,只有在需要重新加载页面时才重新加载。

现在 cafes.js 文件还是空的,下一步就来配置这个文件。

第五步:配置 Vuex 模块的 state 属性

resources/assets/js/modules/cafes.js 文件中,首先从 api 目录下导入咖啡店相关 API,我们将使用其中的 API 请求方法来加载数据:

/*
|-------------------------------------------------------------------------------
| VUEX modules/cafes.js
|-------------------------------------------------------------------------------
| The Vuex data store for the cafes
*/

import CafeAPI from '../api/cafe.js';

现在我们将会导出一个常量作为咖啡店模块,在导入 CafeAPI 的下面添加如下这段代码:

export const cafes = {

}

这就是我们要添加到数据存储器的模块,稍后我们会将其导入到数据存储器。

接下来,我们需要设置上述 Vuex 模块的四个属性( stateactionsmutationsgetters )。

首先,添加一个空的 state 对象:

export const cafes = {
    state: {

    }
}

该状态是所有我们想要跟踪数据的状态,在 cafes 模块中有两个需要跟踪的数据:咖啡店数组,以及存储单个咖啡店的对象。分别对应返回所有咖啡店和单个咖啡店的 API。我们会这样初始化这两个数据:

export const cafes = {
    state: {
        cafes: [],
        cafe: {}
    }
}

根据经验,我们经常遇到的一个问题是显示加载状态。在单页面应用中,加载状态至关重要。HTML/CSS 和其他页面功能通常会在向等待数据加载的用户提供不良UX的数据之前加载。对于我们在状态中跟踪的每个数据,我会为跟踪加载状态的数据状态添加相应的变量。这样我就可以读取这个变量来确定是否显示加载状态。 随着 Vue 被激活,数据被加载后,这个变量会更新,使用该变量的组件也会更新,并相应地显示到页面。相应的状态变量定义如下:

export const cafes = {
    state: {
        cafes: [],
        cafesLoadStatus: 0,
        cafe: {},
        cafeLoadStatus: 0
    },
}

我通常定义状态码如下:

status = 0
status = 1
status = 2
status = 3

这样我们就可以基于数据加载状态在需要的时候相应的提示信息。

第六步:配置 Vuex 模块的 actions 属性

actions 在模块中用于被调用来修改状态。在本教程中,我们会调用一个 action 用于发起 API 请求并提交 mutationsmutations 我们会在下一步中实现。

actions 对象中我们可以添加方法来加载所有咖啡店和单个咖啡店信息:

export const cafes = {
    state: {
        cafes: [],
        cafesLoadStatus: 0,

        cafe: {},
        cafeLoadStatus: 0
    },

    actions: {
        loadCafes( { commit } ){

        },
        loadCafe( { commit }, data ){

        }
    }
};

上述代码 actions 部分有两个需要注意的地方:

  • 每个方法都包含一个名为 commit 的析构参数,该参数通过 Vuex 传入,允许我们提交 mutations 。你还可以传入其他的析构参数,要了解更多关于参数析构的细节,可以参考 lukehoban/es6features 这个 Github 项目。
  • loadCafe 动作包含了一个名为 data 的第二个参数。该参数是一个对象,包含我们想要加载的咖啡店的 ID。

现在,我们来实现这两个方法:

actions: {
    loadCafes( { commit } ){
        commit( 'setCafesLoadStatus', 1 );

        CafeAPI.getCafes()
            .then( function( response ){
                commit( 'setCafes', response.data );
                commit( 'setCafesLoadStatus', 2 );
            })
            .catch( function(){
                commit( 'setCafes', [] );
                commit( 'setCafesLoadStatus', 3 );
            });
    },

    loadCafe( { commit }, data ){
        commit( 'setCafeLoadStatus', 1 );

        CafeAPI.getCafe( data.id )
            .then( function( response ){
                commit( 'setCafe', response.data );
                commit( 'setCafeLoadStatus', 2 );
            })
            .catch( function(){
                commit( 'setCafe', {} );
                commit( 'setCafeLoadStatus', 3 );
            });

    }
},

首先需要注意的是 commit 函数,该函数用于提交一个 mutation,我们会在下一步设置 mutations 。再次重申, state 中的每个数据片段都应该有一个与之对应的 mutation。在上面两个方法中,我们都提交了所使用的状态的加载状态,接下来,调用 API 来加载想要加载的指定信息状态,这些 API 调用定义在 resources/assets/js/api/cafe.js 文件中,之后链式调用 thencatch 方法,前者在 API 请求成功后调用,后者在 API 请求失败后调用, response 变量会传递到这两个方法,以便获取响应数据和请求头。

第七步:配置 Vuex 模块的 mutations 属性

mutations 定义了数据的更新方式,每个模块都有 state ,每个 state 都需要对应的 mutation 来更新,完整工作流如下:

  • 用户调用一个 action
  • 该 action 加载/计算数据
  • 该 action 提交一个 mutation
  • state 被更新
  • getter 将更新后的 state 返回给组件
  • 组件被更新

以上工作流可以通过多种方式来实现,不过相较于 jQuery 或 vanilla JS 的实现,使用 Vuex 更加简单。

我们已经定义了 stateactions ,现在是时候实现 mutations 了,我们在配置 actions 时已经看到了 mutations 的调用,现在只需实现其功能代码即可:

mutations: {
    setCafesLoadStatus( state, status ){

    },

    setCafes( state, cafes ){

    },

    setCafeLoadStatus( state, status ){

    },

    setCafe( state, cafe ){

    }
},

所有 mutations 所做的工作都是设置 state ,所以第一个参数是 state ,这里的 state 是局部模块 state 而不是全局 state,所以我们在第六步中配置的 state 可以被访问,第二个参数是 state 更新后的数据,所以最终实现如下:

mutations: {
    setCafesLoadStatus( state, status ){
      state.cafesLoadStatus = status;
    },

    setCafes( state, cafes ){
      state.cafes = cafes;
    },

    setCafeLoadStatus( state, status ){
      state.cafeLoadStatus = status;
    },

    setCafe( state, cafe ){
      state.cafe = cafe;
    }
},

在每个 mutation 中,我们将局部模块的 state 数据设置为传入的更新后数据,这也正是每个 mutation 所要做的操作。接下来,我们将会配置 getters

第八步:配置 Vuex 模块的 getters 属性

到目前为止,我们已经有了想要跟踪的 state 数据,从 API 接口获取数据的 actions ,以及用于设置 statemutations ,现在需要定义 getters 从模块中获取数据。

我们的 getters 对象需要像这样添加到 cafes 模块中:

getters: {

}

接下来,需要为每一个 state 数据的获取定义一个方法:

getters: {
    getCafesLoadStatus( state ){
      return state.cafesLoadStatus;
    },

    getCafes( state ){
      return state.cafes;
    },

    getCafeLoadStatus( state ){
      return state.cafeLoadStatus;
    },

    getCafe( state ){
      return state.cafe;
    }
}

每个 getter 方法都会传入一个局部模块 state 作为参数并返回相应的 state 数据,这就是 getters 所做的全部工作了!现在我们可以在组件中使用所有这些数据了。

至此,我们的 Vuex 模块已经全部定义好了:

/*
 |-------------------------------------------------------------------------------
 | VUEX modules/cafes.js
 |-------------------------------------------------------------------------------
 | The Vuex data store for the cafes
 */

import CafeAPI from '../api/cafe.js';

export const cafes = {
    /**
     * Defines the state being monitored for the module.
     */
    state: {
        cafes: [],
        cafesLoadStatus: 0,

        cafe: {},
        cafeLoadStatus: 0
    },
    /**
     * Defines the actions used to retrieve the data.
     */
    actions: {
        loadCafes( { commit } ){
            commit( 'setCafesLoadStatus', 1 );

            CafeAPI.getCafes()
                .then( function( response ){
                    commit( 'setCafes', response.data );
                    commit( 'setCafesLoadStatus', 2 );
                })
                .catch( function(){
                    commit( 'setCafes', [] );
                    commit( 'setCafesLoadStatus', 3 );
                });
        },

        loadCafe( { commit }, data ){
            commit( 'setCafeLoadStatus', 1 );

            CafeAPI.getCafe( data.id )
                .then( function( response ){
                    commit( 'setCafe', response.data );
                    commit( 'setCafeLoadStatus', 2 );
                })
                .catch( function(){
                    commit( 'setCafe', {} );
                    commit( 'setCafeLoadStatus', 3 );
                });

        }
    },
    /**
     * Defines the mutations used
     */
    mutations: {
        setCafesLoadStatus( state, status ){
            state.cafesLoadStatus = status;
        },

        setCafes( state, cafes ){
            state.cafes = cafes;
        },

        setCafeLoadStatus( state, status ){
            state.cafeLoadStatus = status;
        },

        setCafe( state, cafe ){
            state.cafe = cafe;
        }
    },
    /**
     * Defines the getters used by the module
     */
    getters: {
        getCafesLoadStatus( state ){
            return state.cafesLoadStatus;
        },

        getCafes( state ){
            return state.cafes;
        },

        getCafeLoadStatus( state ){
            return state.cafeLoadStatus;
        },

        getCafe( state ){
            return state.cafe;
        }
    }
};

第九步:将 Vuex 模块添加到数据存储器

最后,我们还要告诉 Vuex 数据存储器使用 cafes 模块,打开 resources/assets/js/store.js 文件,紧随

Vue.use( Vuex )

之后添加如下这段代码:

/**
 * Imports all of the modules used in the application to build the data store.
 */
import { cafes } from './modules/cafes.js'

并且修改默认导出数据存储器代码如下:

export default new Vuex.Store({
    modules: {
        cafes
    }
});

小结

在这篇教程中,我们创建了一个 Vuex 存储器并为咖啡店配置了一个 Vuex 模块。要想看到对应的效果,编译前端资源后( npm run dev ),可以在开发环境访问 http://roast.test 并打开开发者工具,切换到 Vue 标签页,在 Vuex 部分就可以看到 stategetters 属性:

基于 Laravel + Vue 构建 API 驱动的 LBS 应用系列教程(九) —— 构建 Vuex 模块

下一篇教程中我们演示如何在 Vue 组件中使用 Vuex 模块。

项目源码位于 Github 上: nonfu/roastapp


以上所述就是小编给大家介绍的《基于 Laravel + Vue 构建 API 驱动的 LBS 应用系列教程(九) —— 构建 Vuex 模块》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Database Design and Implementation

Database Design and Implementation

Edward Sciore / Wiley / 2008-10-24 / 1261.00 元

* Covering the traditional database system concepts from a systems perspective, this book addresses the functionality that database systems provide as well as what algorithms and design decisions will......一起来看看 《Database Design and Implementation》 这本书的介绍吧!

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具