vue使用Vuex状态管理模式

目录
  • 1、基于单向数据流问题而产生了Vuex
  • 2、安装及使用
  • 3、核心及使用方法
    • (1)State
    • (2) Getters
    • (3) Mutation
    • (4) Action
    • (5)Modules
  • 4、Vuex和全局对象的不同

1、基于单向数据流问题而产生了Vuex

单向数据流是vue 中父子组件的核心概念,props 是单向绑定的。当父组件的属性值发生变化的时候,会传递给子组件发生相应的变化,从而形成一个单向下行的绑定,父组件的属性改变会流向下行子组件中,但是反之,为了防止子组件无意间修改了父组件中的数据而影响到了其他的子组件的状态,vue 规定了从下往上的数据流是不允许的。当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:

a、多个组件依赖于同一状态。组件之间传参变得特别繁琐,并且兄弟组件之间状态传递无能为力。

b、来自不同视图的行为需要变更同一状态。 经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。

我们为什么不把组件的共享状态抽取出来,以一个全局单例模式管理呢?Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

使用 Vuex 并不意味着你需要将所有的状态放入 Vuex。虽然将所有的状态放到 Vuex 会使状态变化更显式和易调试,但也会使代码变得冗长和不直观。如果有些状态严格属于单个组件,最好还是作为组件的局部状态。应该根据你的应用开发需要进行权衡和确定。

2、安装及使用

CDN 方式: <script src="...vuex.js"></script>
    NPM 方式: npm install vuex --save
    Yarn方式: yarn add vuex
    其他方式:项目初始化是引入依赖
    无论哪种方式都需要  Vue.use(Vuex)来安装 Vuex

3、核心及使用方法

每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 vuex的Vuex 核心 State 、Getters 、Mutation、Action、Module。

(1)State

Vuex也使用了单一状态树来管理应用层级的全部状态。唯一数据源。

单一状态树能够让我们最直接的方式找到某个状态的片段,而且在之后的维护和调试过程中,也可以非常方便的管理和维护。

state存储状态类似于组件中data,在组件中访问状态经常有两种方法:分别为

a、通过 this.$store.state.属性 的方式来访问状态,通常写在computed计算属性中,当然也可以直接通过插值表达式访问;

b、借助mapState 辅助函数。

核心代码如下:

<div id="app">
            {{ mycount }}<br>
            直接插值表达式访问
            {{ this.$store.state.count }}<br>
            {{ myinfoAge }}<br>
        </div>
        <script>
        import Vue from 'vue';
        import Vuex from 'vuex';
        import { mapState } from 'vuex'// 使用辅助函数一定记住引入
        const store = new Vuex.Store({
            // 存储状态数据
            state: {
                count: 0,
                info:{
                    name:"xiaoming",
                    age:18
                }
            },
        )
        new Vue({
            el: '#app',
            store,
            computed:{
                // a、计算属性方式
                mycount(){
                    return this.$store.state.count
                },
                // b、利用辅助函数赋值给对应变量,页面可以直接使用该变量
                 ...mapState({
                    myinfoAge: (state) => state.info.age,
                }),
                // 当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组。下面的简化写法相当于 info: (state) => state.info,
                ...mapState(["info"]),
            }
        })
        </script>

(2) Getters

store的一个计算属性,类比组件的计算属性,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算,Getter 接受 state 作为其第一个参数,在state中的数据发生改变,计算属性重新计算

Getters 的状态存储相当于组件中计算属性,访问方式有三种:

a、通过属性访问

b、通过方法访问

c、通过mapGetters 辅助函数访问

核心代码如下:

<div id="app">
           {{ myInfoLength }}<br>
           直接插值表达式访问
           {{ this.$store.getters.infoLength }}<br>
           {{ myName }}<br>
           {{ infoLength }}
        </div>
        <script>
        import Vue from 'vue';
        import Vuex from 'vuex';
        import { mapGetters  } from 'vuex'// 使用辅助函数一定记住引入
        const store = new Vuex.Store({
            state: {
                info:[
                    {name:"name1",age:18},
                    {name:"name2",age:28}
                ]
            },
            // 存储状态数据
            getters: {
                infoLength: (state) => {
                    return state.info.length;
                },
                getNameByAge: (state) => (age) => {
                    return state.info.find(item => item.age === age).name
                }
            },
        )
        new Vue({
            el: '#app',
            store,
            computed:{
                // a、通过属性访问
                myInfoLength(){
                    return this.$store.getters.infoLength
                }
                // b、通过方法访问
                myName(){
                    return this.$store.getters.getNameByAge(18)
                }
                // c、mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性
                ...mapGetters(["infoLength"])
            }
        })
        </script>

(3) Mutation

前面state和getters两个核心概念都是为了在store存储数据和访问数据的使用,Mutation则提供了对store中数据的修改功能,并且是唯一的更新方式,提交Mutation,Mutation主要包括两部分:字符串的事件类型(type)和一个回调函数(handler),该回调函数的第一个参数就是state。

在视图组件中不能直接修改store容器中的状态,需要先在容器中注册一个事件函数,当需要更新状态时候需要提交触发该事件,同时可以向该事件传递参数。这里需要区别与组件内v-model双向绑定。提交事件方法有一下几种:

a、普通提交方式

b、对象风格提交

c、借助 mapMutations 辅助函数

其核心代码如下:

<div id="app">
            <button @click="handleAdd">点我加一</button>
            <button @click="handleAddForNum">点我加加</button>
            <button @click="handleAddForObj">对象添加</button>
            <button @click="handleAddMap">对象添加</button>
        </div>
        <script>
        import Vue from 'vue';
        import Vuex from 'vuex';
        import { mapMutations  } from 'vuex'// 使用辅助函数一定记住引入
        const store = new Vuex.Store({
            state: {
                count:1
            },
            mutations:{
                // 注册事件
                addCount(state){
                    state.count ++
                },
                addCountForNum(state,num){
                    state.count += num
                },
                addCountForObj(state,payload){
                    state.count += payload.num
                },
                addMap(state){
                    state.count ++
                }
            }
        )
        new Vue({
            el: '#app',
            store,
            methods:{
                // a、普通提交方式
                handleAdd(){
                    this.$store.commit('addCount')
                },
                handleAddForNum(){
                    this.$store.commit('addCountForNum',10)
                },
                // b、对象风格提交
                handleAddForObj() {
                    this.$store.commit({ type: "addCountForObj", num: 100 });
                },
                // c、借助 mapMutations 辅助函数
                ...mapMutations(["addMap"]),
                handleAddMap(){
                    this.addMap()
                }
            }
        })
        </script>

Mutation 需遵守 Vue 的响应规则,Vuex 的 store 中的状态是响应式的,那么当我们变更状态时,监视状态的 Vue 组件也会自动更新。这也意味着 Vuex 中的 mutation 也需要与使用 Vue 一样遵守一些注意事项:最好提前在你的 store 中初始化好所有所需属性。当需要在对象上添加新属性时,你应该使用 Vue.set(obj, 'newProp', 123), 或者以新对象替换老对象。例如,利用对象展开运算符 state.obj = { ...state.obj, newProp: 123 }

注意:Mutation 必须是同步函数。在 mutation 中混合异步调用会导致你的程序很难调试。例如,当你调用了两个包含异步回调的 mutation 来改变状态,你怎么知道什么时候回调和哪个先回调呢?

(4) Action

Action类似于Mutation, 但是是用来代替Mutation进行异步操作的.action 用于异步的修改state,它是通过muation间接修改state的。

context是和store对象具有相同方法和属性的对象.也就是说, 我们可以通过context去进行commit相关的操作, 也可以获取context.state等.

若需要异步操作来修改state中的状态,首先需要action来注册事件,组件视图在通过dispatch分发方式调用该事件,该事件内部提交mutation中的事件完成改变状态操作,总之,通过action这个中介来提交mutation中的事件函数.分发事件方法如下:

a、普通提交方式

b、对象风格提交

c、借助 mapActions 辅助函数

核心代码如下:

<div id="app">
            <button @click="handleAdd">点我加一</button>
            <button @click="handleAddTen">点我加十</button>
            <button @click="handleAddForObj">对象添加</button>
            <button @click="handleAddMap">对象添加</button>
        </div>
        <script>
        import Vue from 'vue';
        import Vuex from 'vuex';
        import { mapMutations,mapActions  } from 'vuex'// 使用辅助函数一定记住引入
        const store = new Vuex.Store({
            state: {
                count:1
            },
            // 注册事件修改state状态值
            mutations:{
                addCount(state){
                    state.count ++
                },
                addCountForNum(state,num){
                    state.count += num
                },
                addCountForObj(state,payload){
                    state.count += payload.num
                },
                addMap(state){
                    state.count ++
                }
            },
            // 注册事件,提交给 mutation
            actions:{
                addAction(context){
                    setTimeout(() => {
                        context.commit('addCount')
                    }, 1000)
                },
                addActionForNum(context,num){
                    setTimeout(() => {
                        context.commit('addCountForNum',num)
                    }, 1000)
                },
                addActionForObj(context,payload){
                    setTimeout(() => {
                        context.commit('addCountForObj',payload)
                    }, 1000)
                },
                addActionMap(context){
                    setTimeout(() => {
                        context.commit('addMap')
                    }, 1000)
                }
            }
        )
        new Vue({
            el: '#app',
            store,
            methods:{
                // a、普通提交方式
                handleAdd(){
                    this.$store.dispatch('addAction')
                },
                handleAddTen(){
                    this.$store.dispatch('addActionForNum',10)
                },
                //  b、对象风格提交
                handleAddForObj(){
                    this.$store.dispatch({
                        type: 'addActionForObj',
                        amount: 10
                    })
                }
                // 借助 mapActions 辅助函数
                ...mapActions(["addActionMap"]),// 相当于...mapActions({addActionMap:"addActionMap"})
                handleAddMap(){
                    this.addActionMap()
                }
            }
        })

组合 Action:组合多个 action,以处理更加复杂的异步流程.store.dispatch 可以处理被触发的 action 的处理函数返回的 Promise,并且 store.dispatch 仍旧返回 Promise。一个 store.dispatch 在不同模块中可以触发多个 action 函数。在这种情况下,只有当所有触发函数完成后,返回的 Promise 才会执行。假设 getData() 和 getOtherData() 返回的是 Promise。

actions: {
            async actionA ({ commit }) {
                commit('gotData', await getData())
            },
            async actionB ({ dispatch, commit }) {
                await dispatch('actionA') // 等待 actionA 完成
                commit('gotOtherData', await getOtherData())
            }
        }

(5)Modules

Vuex允许我们将store分割成模块(Module), 而每个模块拥有自己的state、mutation、action、getters等

4、Vuex和全局对象的不同

(1)Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。

(2)你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

到此这篇关于vue使用Vuex状态管理模式的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • vue的状态管理模式vuex

    vuex是一个专门为vue.js设计的状态管理模式,并且也可以使用devtools进行调试. 备注:本文的示例等代码将会采用es6的语法. 链接 vuex官方中文网站 使用vue和vuex实现的简易商城,仅供参考 vuex是什么? 先引用vuex官网的话: Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. 状态管理模式.集中式存储管理 一听就很高大上,蛮吓人的.在我看来 vuex 就是把需

  • 一篇看懂vuejs的状态管理神器 vuex状态管理模式

    关于vuex类的新闻最近很多,看到眼热就去查了下资料,然后扯出来一堆flux.redux.state.state之类的概念,以及大型工程必要性之类的.看官方手册也是昏昏然. 然而,我还是弄懂了!我准备从demo出发,以同样的一个最简单的demo,演示两种情况下的代码编写情况: 单纯依赖于vue.js 依赖vue.js,也使用了vuex技术 目的是通过对比引出vuex的概念.优势和劣势.也许这是目前最接地气的vuex的介绍吧:).所以无论如何在了解vuex之前,你必须懂得vue.js(好像废话:)

  • 详解vuex状态管理模式

    一.前言 本次接受一个BI系统,要求是能够接入数据源-得到数据集-对数据集进行处理-展现为数据的可视化,这一个系统为了接入公司自身的产品,后端技术采用spring boot,前端采用vue+vuex+axios的项目架构方式,vuex作为vue的状态管理,是尤为重要的部分.这里,我将vuex如何运作和使用做一次总结,有错的地方,望多多提点. 二.vuex简单使用 安装vuex cnpm install vuex --save 在src目录下建立文件夹,命名为store,建立index.js 如图

  • 简述vue状态管理模式之vuex

    了解vuex核心概念请移步 https://vuex.vuejs.org/zh/ 一.初始vuex 1.1 vuex是什么 那么先来看看这两个问题: 什么是vuex?官网说:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式. 按个人通俗理解来说就是:vuex就是用来管理各个组件之间的一些状态,可以理解为这些状态就是公共(共享)部分.此时任何组件都能从中获取状态或者触发一些行为事件. 什么情况下用到vuex?官网说:如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的.确实

  • vue使用Vuex状态管理模式

    目录 1.基于单向数据流问题而产生了Vuex 2.安装及使用 3.核心及使用方法 (1)State (2) Getters (3) Mutation (4) Action (5)Modules 4.Vuex和全局对象的不同 1.基于单向数据流问题而产生了Vuex 单向数据流是vue 中父子组件的核心概念,props 是单向绑定的.当父组件的属性值发生变化的时候,会传递给子组件发生相应的变化,从而形成一个单向下行的绑定,父组件的属性改变会流向下行子组件中,但是反之,为了防止子组件无意间修改了父组件

  • vue store之状态管理模式的详细介绍

    状态管理 一.状态管理(vuex)简介 uex是专为vue.js应用程序开发的状态管理模式.它采用集中存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化.vuex也集成刀vue的官方调试工具devtools extension,提供了诸如零配置的time-travel调试.状态快照导入导出等高级调试功能. Vuex 的思想 当我们在页面上点击一个按钮,它会处发(dispatch)一个action, action 随后会执行(commit)一个mutation, mut

  • 一文详解Pinia和Vuex与两个Vue状态管理模式

    目录 前言 安装 挂载 Vuex Pinia 修改状态 vuex Pinia Pinia解构(storeToRefs) getters Pinia Vuex modules Pinia Vuex 写在最后 前言 Pinia和Vuex一样都是是vue的全局状态管理器.其实Pinia就是Vuex5,只不过为了尊重原作者的贡献就沿用了这个看起来很甜的名字Pinia. 本文将通过Vue3的形式对两者的不同实现方式进行对比,让你在以后工作中无论使用到Pinia还是Vuex的时候都能够游刃有余. 既然我们要

  • 详解vue组件化开发-vuex状态管理库

    Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化.Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试.状态快照导入导出等高级调试功能. 以上是vuex的官方文档对vuex的介绍,官方文档对vuex的用法进行了详细的说明.这里就不再细讲vuex的各个用法,写这篇博客的目的只是帮助部分同学更快地理解并上手vuex.

  • vue.js的状态管理vuex中store的使用详解

    一.状态管理(vuex)简介 vuex是专为vue.js应用程序开发的状态管理模式.它采用集中存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化.vuex也集成刀vue的官方调试工具devtools extension,提供了诸如零配置的time-travel调试.状态快照导入导出等高级调试功能. 二.状态管理核心 状态管理有5个核心,分别是state.getter.mutation.action以及module.分别简单的介绍一下它们: 1.state state为

  • Vue详细讲解Vuex状态管理的实现

    目录 什么是状态管理 Vuex的使用 单一状态树和mapState辅助函数 1. 单一状态树 2. mapState辅助函数 getters的基本使用 1. getter的使用 2. getters第二个参数 3. getters的返回函数 (了解) 4. mapGetters的辅助函数 mutation基本使用 1. mutation携带数据 2. mutation重要原则 actions的基本使用 1. actions的分发操作 2. actions的辅助函数 3. actions的异步操作

随机推荐