vuex

对 vue 应用中多个组件的共享状态进行集中式的管理(读/写)
GitHub: https://github.com/vuejs/vuex
在线文档: https://github.com/vuejs/vuex

单向数据流理念

  1. state: 驱动应用的数据源(data数据)
  2. view: 以声明方式将state映射到视图(初始化数据和更新显示数据)
  3. actions: 响应在 view 上的用户输入导致的状态变化(多个事件函数改变数据)

核心概念

  • state vuex 管理的状态对象(初始化data)
  • mutations 直接更新state的方法(回调函数)的对象
  • actions 事件回调函数的对象, 发送ajax请求跟后台交互
  • getter 计算属性
  • modules 外部模板(xxx.vue)
  • store 在main.js配置后会生成一个$store属性, 它就是store对象,
    其中有属性state, getters
    方法dispatch(actionName, data): 分发调用action

使用

下载: npm install --save vuex
创建: (src/store/store.js)新建store.js(存放核心管理对象模块), 向外暴露store对象

  1. store.js
/**
 * vuex 的 store 对象模块
 */
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
/*
state 对象
类似于 data
*/
const state = {
    count: 0 // 初始化状态数据
}
/*
mutations 对象
包含多个方法: 能直接更新 state 
mutation 只能包含更新 state 的同步代码, 也不会有逻辑
mutation 由 action 触发调用: commit('mutationName')
*/
const mutations = {
    INCREMENT(state) {
        state.count++
    },
    DECREMENT(state) { // ctrl + shift + x
        state.count--
    }
}
/*
actions 对象
包含多个方法: 触发 mutation 调用, 间接更新 state 
action 中可以有逻辑代码和异步代码
action 由组件来触发调用: this.$store.dispatch('actionName')
*/
const actions = {increment({commit}) {
        commit('INCREMENT')
    },
    decrement({commit}) {
        commit('DECREMENT')
    },
    incrementIfOdd({commit,state}) {
        if (state.count % 2 === 1) {
            commit('INCREMENT')
        }
    },
    incrementAsync({commit}) {
        setTimeout(() => {
            commit('INCREMENT')
        }, 1000)
    }
}
/*
getters 对象
包含多个 get 计算计算属性方法
*/
const getters = {
    oddOrEven(state) {
        return state.count % 2 === 0 ? '偶数' : '奇数'
    },
    count(state) {
        return state.count
    }
}
// 向外暴露 store 实例对象
export default new Vuex.Store({
    state,
    mutations,
    actions,
    getters
})
  1. 在main.js配置
import store from './store'
new Vue({
    el: '#app',
    router,
    store,  //这里配置后所有的组件对象多了个属性: $store
    render: h => h(App)
})
  1. 组件中使用
<template>
    <div>
        <p>clicked: {{$store.state.count}} times, count is {{oddOrEven}}</p>
        <button @click="increment">+</button>
        <button @click="decrement">-</button>
        <button @click="incrementIfOdd">increment if odd</button>
        <button @click="incrementAsync">increment async</button>
    </div>
</template>
<script>
export default {
    computed: {
        oddOrEven() {
            return this.$store.getters.oddOrEven;
        }
    },
    methods: {
        increment() {
            this.$store.dispatch("increment");
        },
        decrement() {
            this.$store.dispatch("decrement");
        },
        incrementIfOdd() {
            this.$store.dispatch("incrementIfOdd");
        },
        incrementAsync() {
            this.$store.dispatch("incrementAsync");
        }
    }
};
</script>
<style>
</style>

上面代码可以优化

<template>
    <div>
        <p>clicked: {{count}} times, count is {{oddOrEven2}}</p>
        <button @click="increment">+</button>
        <button @click="decrement">-</button>
        <button @click="incrementIfOdd">increment if odd</button>
        <button @click="incrementAsync">increment async</button>
    </div>
</template>
<script>
import { mapGetters, mapActions } from "vuex";
export default {
    computed: mapGetters({
        // 名称和getters中的名称不一致(oddOrEven2: "oddOrEven")
        oddOrEven2: "oddOrEven",
        count: "count"
    }),
    methods: mapActions([
        // 名称和actions中的名称一致
        "increment",
        "decrement",
        "incrementIfOdd",
        "incrementAsync"
    ])
};
</script>
<style>
</style>

分模块使用

创建store文件夹(src/store), 在文件夹下创建以下文件

  1. index.js store的入口文件(相当于store.js), vuex核心管理对象, 向外暴露store对象
import Vue from 'vue'
import Vuex from 'vuex'

import state from './state'
import mutations from './mutations'
import actions from './actions'
import getters from './getters'

Vue.use(Vuex)

export default new Vuex.Store({
    state,
    mutations,
    actions,
    getters
})
  1. state.js 初始化变量(相当于data)
export default {
    todos: []
}
  1. actions.js 接受组件事件, 触发mutation调用, 本身不做逻辑处理, 只是分发事件
    this.$.store.dispatch('事件名',参数)
import {
    ADD_TODO,
    DELETE_TODO,
    SELECT_ALL_TODOS,
    CLEAR_ALL_COMPLETED
} from './mutations-types'

export default {
    // 组件的addTodo方法,todo为参数,  commit把方法提交到mutation
    addTodo({commit}, todo) {
        // 这里传参必须是对象包裹
        commit(ADD_TODO, {todo})
    },
    deleteTodo({commit}, index) {
        commit(DELETE_TODO, {index})
    },
    selectAllTodos({commit}, check){
        commit(SELECT_ALL_TODOS, {check})
    },
    clearAllCompleted({commit}){
        commit(CLEAR_ALL_COMPLETED)
    }
}
  1. mutations-types.js 定义mutations的名称常量模块, 这样做的好处解决commit中名称命名问题, 同时防止了名称重复命名
export const ADD_TODO = 'add_todo'   

export const DELETE_TODO = 'delete_todo'   

export const SELECT_ALL_TODOS = 'select_all_todos'   

export const CLEAR_ALL_COMPLETED = 'clear_all_completed' 
  1. mutations.js 接受actions.js分发过来的事件, 编写逻辑处理, 改变state 中的变量
import {
    ADD_TODO,
    DELETE_TODO,
    SELECT_ALL_TODOS
} from './mutations-types'

export default {
    [ADD_TODO](state, {todo}) {
        state.todos.unshift(todo)
    },
    [DELETE_TODO](state, {index}) {
        state.todos.splice(index, 1)
    },
    [SELECT_ALL_TODOS](state, {check}) {
        state.todos.forEach(todo => todo.complete = check)
    },
    [CLEAR_ALL_COMPLETED](state) {
        state.todos = state.todos.filter(todo => !todo.complete)
    },
}
  1. getters.js 计算属性, 对state数据处理
export default{
   // 总数量
   totalCount (state){
       return state.todos.length
   },
   // 完成数量
   completeCount (state){
       return state.todos.reduce(
           (preTotal, todo) => preTotal + (todo.complete ? 1 : 0),0);
   },
   // 判断是否全部选中
   isAllCheck (state, getters){
       return getters.totalCount===getters.completeCount && state.todos.length>0
   }

}

组件中读取数据

  • state 引入mapState, 在computed中读取
  • getters 引入mapGetters, 在computed中读取
import {mapState} from 'vuex'
export default {
    computed: {
        ...mapState(['todos'])
    }
}

组件中修改数据

  • this.$store.dispatch('名称',参数)
  • mapActions定义事件
<button class="btn btn-danger" @click="deleteItem">删除</button>

methods: {
        deleteItem() {
            this.$store.dispatch('deleteTodo', index)
        }
    }
<button class="btn btn-danger" @click="clearAllCompleted">清除已完成任务</button>

import {mapGetters,mapActions} from 'vuex'
methods: {
        ...mapActions(['clearAllCompleted'])
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,277评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,689评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,624评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,356评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,402评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,292评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,135评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,992评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,429评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,636评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,785评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,492评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,092评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,723评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,858评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,891评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,713评论 2 354

推荐阅读更多精彩内容

  • vuex 场景重现:一个用户在注册页面注册了手机号码,跳转到登录页面也想拿到这个手机号码,你可以通过vue的组件化...
    sunny519111阅读 8,015评论 4 111
  • 上一章总结了 Vuex 的框架原理,这一章我们将从 Vuex 的入口文件开始,分步骤阅读和解析源码。由于 Vuex...
    你的肖同学阅读 1,786评论 3 16
  • vuex是一个状态管理模式,通过用户的actions触发事件,然后通过mutations去更改数据(你也可以说状态...
    Ming_Hu阅读 2,023评论 3 3
  • Vuex 是什么? Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有...
    skycolor阅读 833评论 0 1
  • 读书的时候,一有小孩子骂脏话。就听到老师教育我们要有教养。同班有个男同学特别调皮,下课经常偷偷的趁女孩子不注意剪女...
    小糖棠阅读 1,602评论 0 6