为什么会有 Vuex 这个东西 ?

现代前端框架主要解决的是 事件 -> 状态 -> UI 将传统前端在两个过程的代码剥离出来,变得更加容易维护;

vue的声明式渲染,解决了 状态 和 UI 的同步问题,从而使我们不需要由于状态发生改变去写大量的命令式改变 dom 的代码。

而类似于 vuex 这类状态管理的库,则解决了 事件 -> 状态 这个过程的维护问题。这类库所做的事情就是管理从 事件源映射到状态变化 这个过程(将这个映射过程从视图组件中剥离出来,组织好这一部分的代码,在组件外部进行状态的管理)

具体表现就是一个全局的数据中心 store 配置,每个组件进行更新的时候就通知数据中心,数据中心改变后,再去触发每个调用它的组件进行更新(这种更新是响应式的);几个核心概念就是 mutations里的方法可以直接 mutatestore 中的状态,并且 mutation 过程必须同步的,需要通过 commit 去触发;而 actions 则允许异步的操作,通过 commit 去触发 mutation ,达到间接修改 store的目的,action 本身需要通过 disptch去触发。

Vuex与全局对象的区别

其实,vuex 与全局对象有一定的共同之处,那就是状态会被全局共享,无论是嵌套多少组件…

每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。Vuex 和单纯的全局对象有以下两点不同:

  1. Vuex 的状态存储是 响应式 的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到 高效更新
  2. 你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

Vuex常见的应用场景

管理状态与共享状态

应用简单时,可以使用 propevent 来完成 父子组件 的通信。使用 global event bus(event bus)来实现 简单的非父子组件之间的跨组件 通信。但对于 多层级组件嵌套 等较为复杂的场景,使用 vuex 能更好地应对。(使用 event bus 的缺点是当状态较复杂,调用组件非常多,要挨个依次通知所有组件更新;每个组件对这个组件进行的状态更新都要通知监听该事件的所有组件;这样会变得非常复杂)(你通知我, 我通知你, 你通知他, 他通知我 ... 大家之间是直接相互作用的)

vuex 状态管理模型,拥有一个统一的数据中心Store,Store用来维护状态数据;每个组件进行更新的时候就通知数据中心,数据中心改变后,再去统一触发每一个调用它的组件进行更新(相当于由数据中心来统筹状态变化以及状态变化的分发,而不是由每个vue组件直接去操作state) (有点类似于中介者模式, 大家把所有各种类型的信息都反馈给中介, 然后再由中介分发给订阅了某个类型信息的用户)

图解

vuex 是通过将 state 作为数据中心,各个组件 共享 state 来实现跨组件通信的, 此时的数据完全独立于组件。(点击不同模块的操作,不再需要去发送乱七八糟的事件, 只是去调用事件中心里的 mutation 动作, 从而实现模块间共享状态的功能)

需要构建一个中大型单页应用时,很可能会考虑如何更好地 在组件外部 管理状态

vuex更多地用于解决 跨组件通信 (多层嵌套组件之间的通信问题)以及作为 数据中心集中式存储数据 (管理应用中错综复杂的状态关系)

vuex 作为数据存储中心

vuexstate在单页应用的开发中本身具有一个 数据库 的作用,可以将组件用到的数据存储在 state中,并在 actions中封装数据读写的逻辑。目前主要有两种数据会使用 vuex进行管理

  1. 组件之间 全局共享 的数据
  2. 通过后端异步请求的数据

实际项目开发中更多的是用到第二种,即把通过后端异步请求的数据都纳入 vuex 状态管理,在 actions 中封装数据的增删改查等逻辑,这样可以在一定程度上对前端的逻辑代码进行分层,使组件中的代码更多地关注页面交互与数据渲染等 视图层 的逻辑,而异步请求与状态数据的持久化等则交由 vuex 管理

一般全局数据,会使用到 vuex 来管理。比如 用户数据,系统数据 等,这些数据很多组件中都会使用,我们当然可以每次使用的时候都去请求,但是出于程序员的“洁癖”、“抠”等等优点,还是希望一次请求,到处使用。

这时候很自然的想到存储在 localStorage 中,但是有个问题是,这些数据可能会变,如果没能及时 同步 的话,就会用到不正确的数据,即使做了数据同步,但是 localStorage 中的数据不是响应式的,不能自动更新使用到这些数据的地方。这时候就想要开始使用 vuex了。

Vuex代码的组织方式

vue-router 类似,有非模块化写法与模块化写法(其实无论何种写法本质上是一样的,目的就是导出一份 router或者 store 的配置数据)

以管理 count 与 用户信息 userinfo 为例,介绍 vuex代码的组织方式

核心概念 state,getter,mutation,action,module

vuex 需要遵守的规则

应用层级的状态应该集中到 单个 store 对象中

mutation是直接操作state的方法(唯一能改变状态的方法),过程要求必须同步

action 通过commit去触发mutation,从而间接修改状态,优点是允许异步逻辑,

非模块化写法
// 1.安装 vuex

// 2.在入口文件中引入
// main.js
import Vuex from 'vuex' // 3.Vue使用 vuex 插件
Vue.use(Vuex) // 4.生成数据管理中心 store
const store = new Vuex.Store({
    state: {
        userinfo: null, // 需要给定初始值
        count: 0
    },
    // 直接通过mutation方法来mutate操作state; 只能以同步的方式; mutation方法需要通过commit来触发
    mutations: {
        userinfo: function (state, payload) {
              state.userinfo = options
            localStorage.userinfo = JSON.stringify(state.userinfo)
        },
        increment: function (state, payload) {
            state.count += payload.amount
        }
    },
    // 通过commit触发mutations里的mutation方法, 以此间接修改 state; 允许异步操作;action方法需要通过dispatch来触发
    actions: {
        increment: function (context, payload) {
            context.commit('increment', payload)
        },
        incrementAsync: function (context) {
            // 异步请求数据
            setTimeout(() => {
                var amount = 10; // 模拟异步请求得到数据
                context.commit('increment', { amount })
            }, 1000)
        },
        async userinfo (context) {
            let response = await getUserInfo() // 异步请求后端数据 方法需要 import
            if (response.ok) {
                let json = await response.json()
                context.commit('userinfo', json)
            }
        }
    },
    getters: {// 处理、过滤数据     }
}) // 5.通过 store 配置参数注入状态管理,从而任何组件可通过 this.$store 访问状态中心
new Vue({
    el: '#app',
    store, // (*)
    render: function (h) {
        return h(App)
    }
})
模块化写法
// 1.安装vuex

// 2.引入
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
// import ... // 3.Vue使用 vuex 插件
Vue.use(Vuex) // 4.分模块生成数据管理中心
// 配置 userinfo 状态模块 (还能再单独拆出一个文件,然后import进来)
const moduleA = {
    state: {
        userinfo: null // 需要初始化响应式数据
    },
    mutations: {
        userinfo: function (state, options) {
            state.userinfo = options
            localstorage.userinfo = JSON.stringify(state.userinfo)
        }
    },
    actions: {
        async userinfo (context) {
            async userinfo (context) {
                let response = await response.json()
                if (response.ok) {
                    let json = await response.json()
                    context.commit('userinfo', json)
                }
            }
        },
        getters: {// 处理、过滤数据         }
    }
} // 配置 count 状态模块 (还能再单独拆出一个文件,然后import进来)
const moduleB = {
    state: {
        count: 1,
    },
    mutations: {
        increment:function (state, payload) {
            state.count += payload
        },
    },
    actions: {
        increment: function (context, payload) {
              context.comit('increment', payload)  
        },
          incrementAsync: function (context) {
            // 异步请求数据
            setTimeout(() => {
                var amount = 10; // 模拟异步请求得到数据
                context.commit('increment', { amount })
            }, 1000)
        },  
    },
    getters: {
        doubleCount (state) {
            return state.count * 2
        }
    }
} // 5.导出一份 store 的配置
export default new Vuex.Store({
    modules: { // 这里与非模块化写法有点不一样;原来整个对象是一份配置...
        a: moduleA,
        b: moduleB,
    }
}) // store.state.a // -> moduleA 的状态
// store.state.b // -> moduleB 的状态 // 6.在根脚本 main.js 中引入 store 配置
import store from './store'
...
// 并通过 store 配置参数注入状态管理,从而任何组件可通过 this.$store 访问状态中心
new Vue({
    el: '#app',
    router,
    store,
    render: function (h) {
        return h(App);
    }
});

在不同组件中使用或操作状态

// 根组件
// App.vue
// 在生命周期中触发全局共享数据的获取
...
mounted () {
    if (!this.$store.state.userinfo) { // this.$store.state.a.userinfo 模块化写法的话
        this.$store.dispatch('userinfo')
    }
} // 使用 state 的数据
computed: {
    userinfo () {
        return this.$store.state.userinfo
        // return this.$store.state.a.userinfo // 模块化写法的话
    },
    count () {
        return this.$store.state.count
        // return this.$store.state.b.count // 模块化写法的话
    }
}
// 子组件
// NavBar.vue
...
// 改变 state 的数据
methods: {
    // 使用 commit 触发 mutations 中的 mutation 方法,直接修改 state 中的数据
    addOne () {
        this.$store.commit('increment', { amount: this.price })
    },
    // 使用 dispatch 触发 actions 中的 action 方法;异步修改 state 中的数据
    addTenAsync () {
        this.$store.dispatch('incrementAsync')
    }
} // 使用 state 的数据
computed: {
    userinfo () {
        return this.$store.state.userinfo
        // return this.$store.state.a.userinfo // 模块化写法的话
    }
}
// 路由页面组件
// Manage.vue
...
// 改变 state 的数据
methods: {
    addTwo () {
        this.$store.commit('increment', { amount: this.price })
    }
} // 使用 state 的数据
computed: {
    count () {
        return this.$store.state.count
        // return this.$store.state.b.count // 模块化写法的话
    }
},

总之,使用了 vuex 来管理状态,点击不同模块的操作,不再需要去发送乱七八糟的事件, 只是去调用事件中心里的 mutation 动作, 从而实现模块间共享状态的功能;修改一处,全局共享(无论是组件还是路由页面组件都能同步)

最后,再看看 vuex 官网的这张说明图,是不是更加清晰了呢!

虚线绿框里即vuex做的事

-项目地址- vuex-demo

[vue]初探vue生态核心插件Vuex的更多相关文章

  1. vue从入门到精通之【vuex】(七)

    vue从入门到精通之[vuex](七) vuex一个公用的大仓库,Vuex 可以帮助我们管理共享状态,并附带了更多的概念和框架. Vuex 实现了一个单向数据流,在全局拥有一个 state 存放数据, ...

  2. vue.js 开发生态总结

    ---title: Vue 1.0 的技术栈date: 2016-09-26 00:48:50tags:category:--- ## vuejs概述 Vue.js是用于构建交互式的Web界面的库.它 ...

  3. 【vue】vue +element 搭建项目,vuex中的store使用

    概述: 每一个 Vuex 应用的核心就是 store(仓库).“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state).Vuex 和单纯的全局对象有以下两点不同: Vuex 的 ...

  4. day 87 Vue学习六之axios、vuex、脚手架中组件传值

      本节目录 一 axios的使用 二 vuex的使用 三 组件传值 四 xxx 五 xxx 六 xxx 七 xxx 八 xxx 一 axios的使用 Axios 是一个基于 promise 的 HT ...

  5. [译]怎样在Vue.js中使用jquery插件

    原文:http://gambardella.info/2016/09/05/guide-how-to-use-vue-js-with-jquery-plugins 使用Vue真的太棒了,但是也有可能使 ...

  6. Vue 爬坑之路—— 使用 Vuex + axios 发送请求

    Vue 原本有一个官方推荐的 ajax 插件 vue-resource,但是自从 Vue 更新到 2.0 之后,官方就不再更新 vue-resource 目前主流的 Vue 项目,都选择 axios  ...

  7. day 84 Vue学习六之axios、vuex、脚手架中组件传值

    Vue学习六之axios.vuex.脚手架中组件传值   本节目录 一 axios的使用 二 vuex的使用 三 组件传值 四 xxx 五 xxx 六 xxx 七 xxx 八 xxx 一 axios的 ...

  8. 【Vue】Vue学习(四)-状态管理中心Vuex的简单使用

    一.vuex的简介 Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.Vuex背后的基本思想,就是前面所说的单向数据流.图4就是Vuex实现单向数据流的示意图.    Store     ...

  9. vue初探

    vue初探 很多同学一定都听过MVVM.组件.数据绑定之类的专业术语,而vue框架正是这样的一种框架.vue的作用是:通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件. 第一部分:vue介 ...

随机推荐

  1. ios遇到的坑

    总结体会:很多ios兼容性问题都是由于body设置了height:100% ios中input输入不了 在ios中margin属性不起作用 设置html body的高度为百分比时,margin-bot ...

  2. 理解Spark运行模式(三)(STANDALONE和Local)

    前两篇介绍了Spark的yarn client和yarn cluster模式,本篇继续介绍Spark的STANDALONE模式和Local模式. 下面具体还是用计算PI的程序来说明,examples中 ...

  3. flex盒子布局

    看过很多对于弹性盒子flex的简介,但还是觉得阮一峰大神的解析和张鑫旭大神(旧版flex)的解析比较容易理解,下面,我以自己的理解来叙述关于flex弹性布局! 1.概念(容器和项目) 在flex中,有 ...

  4. head first 设计模式第一章笔记

    设计模式是告诉我们如何组织类和对象以解决某种问题. 学习设计模式,也就是学习其他开发人员的经验与智慧,解决遇到的相同的问题. 使用模式的最好方式是:把模式装进脑子,然后在设计的时候,寻找何处可以使用它 ...

  5. 万恶之源-与python的初识

    1.计算机基础知识 ​ 1.cpu: 人类的大脑 运算和处理问题 ​ 2.内存: 临时存储数据 断电就消失了 ​ 3.硬盘: 永久 存储数据 ​ 4.操作系统:是一个软件 控制每个硬件之间数据交互 2 ...

  6. react create-react-app使用less 及关闭eslint

    使用less和关闭eslint都需要先运行命令 npm run  eject 来暴露配置文件,(不可逆的) 一.less使用 运行命令安装less npm install less less-load ...

  7. 【2018寒假集训Day 7】【最短路径】三种算法的模板

    Luogu单源最短路径模版题 dijkstra #include<cstdio> #include<vector> using namespace std; const int ...

  8. Python-Re正则表达式库

    来源:中国MOOC北京理工大学Python教学团队 链接:https://www.icourse163.org/learn/BIT-1001870001#/learn/content?type=det ...

  9. LESSON 4- Entropy and Asymptotic Equipartition Property

    1.        Entropy 2.        序列熵(无记忆,有记忆,马尔科夫) 3.   Fixed-to-variable-length codes  (给n个输出symbols进行变长 ...

  10. myql数据库,sql横排转竖排以及竖排转横排,oracle的over函数的使用

    一.引言 前些日子遇到了一个sql语句的横排转竖排以及竖排转横排的问题,现在该总结一下,具体问题如下: 这里的第二题和第三题和下面所讲述的学生的成绩表是相同的,这里给大家留一下一个念想,大家可以自己做 ...