Skip to content

Vuex 模块化实现待办事项的状态管理 #5

Open
@lin-xin

Description

@lin-xin

前言

在vue里,组件之间的作用域是独立的,父组件跟子组件之间的通讯可以通过prop属性来传参,但是在兄弟组件之间通讯就比较麻烦了。比如A组件要告诉一件事给B组件,那么A就要先告诉他们的爸组件,然后爸组件再告诉B。当组件比较多,要互相通讯的事情很多的话,爸组件要管他们那么多事,很累的。vuex正是为了解决这个问题,让多个子组件之间可以方便的通讯。

项目介绍

image

待办事项中的一个事件,它可能拥有几个状态,未完成、已完成、已取消或被删除等。这个事件需要在这多种状态之间切换,那么使用vuex来管理也是非常方便的。

来看一下vuex怎么完成状态管理的:

image

所有组件都是调用actions,分发mutation去修改state,然后state经过getter又更新到各个组件里。state又通过localStorage存储数据到本地,下次重新打开时再读取保存的数据。

模块化

为什么要用模块化?当我们的项目比较大,组件很多,功能也多,会导致state里要存放很多内容,整个 store 都会很庞大,很难管理。

我模块化的store目录如下:

|-store/                   // 存放vuex代码
|   |-eventModule          // 事件模块
|   |   |-actions.js
|   |   |-getters.js
|   |   |-index.js
|   |   |-mutations.js
|   |   |-state.js
|   |-themeModule           // 主题颜色模块
|   |   |-actions.js
|   |   |-getters.js
|   |   |-index.js
|   |   |-mutations.js
|   |   |-state.js
|   |-index.js              // vuex的核心,创建一个store

可以看到,每个模块拥有自己的state、mutation、action、getter,这样子我们就可以把我们的项目根据功能划分为多个模块去使用vuex了,而且后期维护也不会一脸懵逼。

状态管理

接下来,我们来看看vuex完成状态管理的一个流程。
举个栗子:一个待办事项,勾选之后,会在未完成列表里移除,并在已完成的列表里出现。这个过程,是这个待办事项的状态发生了改变。勾选的时候,是执行了一个方法,那我们就先写这个方法。在 event_list.vue 文件里新建一个moveToDone方法。

methods: {
    moveToDone(id){ //移至已完成
        this.$store.dispatch('eventdone', id);
    }
}

在 moveToDone 方法中通过 store.dispatch 方法触发 action, 接下来我们在 eventModule/actions.js 中来注册这个 action, 接受一个 id 的参数。

export default {
    eventdone = ({ commit }, param) =>{
        commit('EVENTDONE',{id: param});
    }
}

action 通过调用 store.commit 提交载荷(也就是{id: param}这个对象)到名为'EVENTDONE'的 mutation,那我们再来注册这个 mutation

export default {
    EVENTDONE(states,obj){
        for (let i = 0; i < states.event.length; i++) {
            if (states.event[i].id === obj.id) {
                states.event[i].type = 2;
                states.event[i].time = getDate();
                var item = states.event[i];
                states.event.splice(i, 1);          // 把该事件在数组中删除
                break;
            }
        }
        states.event.unshift(item);                 // 把该事件存到数组的第一个元素
        local.set(states);                          // 将整个状态存到本地
    }
}

通过 mutation 去修改 state, state里我们存放了一个 event 属性

export default {
    event: []
};

在组件中要获得这个 state 里的 event, 那就需要写个getters

export default {
    getDone(states){
        return states.event.filter(function (d) {
            if (d.type === 2) {                 // type == 2表示已完成
                return d;                       // 返回已完成的事件
            }
        });
    }
};

然后每个module里都有一个index.js文件,把自己的state、mutation、action、getters都集合起来,就是一个module

import * as func from '../function';
import actions from './actions.js';
import mutations from './mutations.js';
import state from './state.js';
import getters from './getters.js';

export default {
    state,
    getters,
    actions,
    mutations
}

在 store/index.js 里创建一个 store 对象来存放这个module

import Vue from 'vue';
import Vuex from 'vuex';
import event from './eventModule';
Vue.use(Vuex);
export default new Vuex.Store({
    modules: {
        event
    }
});

最后在 event_list.vue 组件上,我们通过计算属性 computed 来获取到这个从未完成的状态改变到已完成的状态,我们要用到 store 这个对象里的getters

computed: {
    getDone(){
        return this.$store.getters.getDone;
    }
}

这样子,完成了 '未完成' => '已完成' 从提交修改到更新视图读取的整个流程,也是 vuex 工作的整个流程。通过 module 的封装,更加方便多模块项目的开发和维护。

演示地址 : demo

源码地址 : notepad

Activity

libin1991

libin1991 commented on Mar 15, 2017

@libin1991

有报错啊

lin-xin

lin-xin commented on Mar 15, 2017

@lin-xin
OwnerAuthor

@libin1991 报什么错啊

totchina

totchina commented on Mar 15, 2017

@totchina

非常详细,谢谢

ghost

ghost commented on Mar 16, 2017

@ghost

localEvent.js?961b:20 Uncaught ReferenceError: lx_notepad is not defined
at eval (eval at (app.js:723), :19:28)
at Object. (app.js:723)
at webpack_require (app.js:660)
at fn (app.js:84)
at Object.eval (eval at (app.js:877), :1:119)
at eval (eval at (app.js:877), :22:30)
at Object. (app.js:877)
at webpack_require (app.js:660)
at fn (app.js:84)
at Object.eval (eval at (app.js:898), :3:65)

ghost

ghost commented on Mar 16, 2017

@ghost

报的这个错 lx_notepad这个东西是什么?

lin-xin

lin-xin commented on Mar 16, 2017

@lin-xin
OwnerAuthor

@liangxuxuxu 这个是本地存储的 item 名

ghost

ghost commented on Mar 16, 2017

@ghost

现在我该怎么改这个 直接存在locastorage里面吗?

orallin

orallin commented on Mar 16, 2017

@orallin

报错……node_modules下不来~你用的应该是mac吧

lin-xin

lin-xin commented on Mar 16, 2017

@lin-xin
OwnerAuthor

@orallin 我用windows啊,你用 cnpm 试试。

AquariusBaby

AquariusBaby commented on Mar 22, 2017

@AquariusBaby

楼主大大,你项目里我咋没看到webpack.config啊,新手勿喷,谢谢!

lin-xin

lin-xin commented on Mar 23, 2017

@lin-xin
OwnerAuthor

@AquariusBaby 项目用vue-cli生成的,在build/webpack.base.conf.js就是了。

AquariusBaby

AquariusBaby commented on Mar 23, 2017

@AquariusBaby

恩恩,看到了,之前一直用的webpack-simple。^-^

leochen-g

leochen-g commented on Jul 12, 2017

@leochen-g

非常不错的解释,正在找Vuex的详解呢

Dzhaolei

Dzhaolei commented on Aug 1, 2017

@Dzhaolei

一脸懵逼的来,一脸懵逼的走

QTTQ

QTTQ commented on Sep 4, 2017

@QTTQ

吊炸天,但还有点蒙蒙的

Harrymiracle

Harrymiracle commented on Sep 16, 2017

@Harrymiracle

非常受用 谢谢!

InterfaceYang

InterfaceYang commented on Sep 20, 2017

@InterfaceYang

楼主大大,vue.use(vuex) 会提示vuex只能install一次,,,,,然后就没有然后了

Luying0829

Luying0829 commented on Aug 23, 2018

@Luying0829

我的也报错...... node_modules下载了,但是npm run dev 就是跑不起来
用了CNPM试了下,也不行 一直报错

mmfishlxy

mmfishlxy commented on Aug 13, 2019

@mmfishlxy

做得特别棒 正在看你的代码

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @totchina@lin-xin@libin1991@InterfaceYang@leochen-g

        Issue actions

          Vuex 模块化实现待办事项的状态管理 · Issue #5 · lin-xin/blog