Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
lin-xin opened this issue Mar 14, 2017 · 19 comments
Open

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

lin-xin opened this issue Mar 14, 2017 · 19 comments
Labels

Comments

@lin-xin
Copy link
Owner

lin-xin commented Mar 14, 2017

前言

在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

@lin-xin lin-xin added the vue label Mar 14, 2017
@libin1991
Copy link

有报错啊

@lin-xin
Copy link
Owner Author

lin-xin commented Mar 15, 2017

@libin1991 报什么错啊

@totchina
Copy link

非常详细,谢谢

@ghost
Copy link

ghost commented Mar 16, 2017

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
Copy link

ghost commented Mar 16, 2017

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

@lin-xin
Copy link
Owner Author

lin-xin commented Mar 16, 2017

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

@ghost
Copy link

ghost commented Mar 16, 2017

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

@orallin
Copy link

orallin commented Mar 16, 2017

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

@lin-xin
Copy link
Owner Author

lin-xin commented Mar 16, 2017

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

@AquariusBaby
Copy link

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

@lin-xin
Copy link
Owner Author

lin-xin commented Mar 23, 2017

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

@AquariusBaby
Copy link

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

@leochen-g
Copy link

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

@Dzhaolei
Copy link

Dzhaolei commented Aug 1, 2017

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

@QTTQ
Copy link

QTTQ commented Sep 4, 2017

吊炸天,但还有点蒙蒙的

@Harrymiracle
Copy link

非常受用 谢谢!

@InterfaceYang
Copy link

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

@Luying0829
Copy link

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

@mmfishlxy
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests