当前位置: 首页 > news >正文

Vue 入门到实战 十一 Vuex

目录

11.1状态管理与应用场景

1)state

2)Getters

3)Mutations

4)Actions

5)Module

11.2Vuex的安装与基本应用

11.3Vuex的核心概念


一句话解释vuex:就是单独成立一个组件,这个组件存储共享的数据,其他组件都可以从这个共享组件里面抽取数据。这就是vuex的作用。

11.1状态管理与应用场景

本章主要讲解了Vuex的基本用法。通过本章的学习,掌握Vuexstategettersmutationsactions等核心概念,掌握如何使用Vuex进行状态管理。

状态管理,管理的是全局状态,即全局变量。Vuex是一个专为Vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

大白话:Vuex 是一个插件,可以帮我们管理 Vue 通用的数据 (多组件共享的数据)。例如:购物车数据 个人信息数

状态(state:驱动应用的数据源,即组件中的data

视图(view:以声明方式将状态映射到视图,如{{counter}}

操作action:响应在视图上的用户输入导致的状态变化,即组件的函数methods

1)state

state是存储的单一状态,是存储的基本数据。

2)Getters

getters是store的计算属性,对state的加工,是派生出来的数据。就像computed计算属性一样,getter返回的值会根据它的依赖被缓存起来,且只有当它的依赖值发生改变才会被重新计算。

3)Mutations

mutations提交更改数据,使用store.commit方法更改state存储的状态。(mutations同步函数)

4)Actions

actions像一个装饰器,提交mutation,而不是直接变更状态。(actions可以包含任何异步操作)

5)Module

Module是store分割的模块,每个模块拥有自己的state、getters、mutations、actions。

在较大型的项目中,将有许多组件用到同一变量,比如,一个登录的状态,很多页面组件都需要这个信息。在这样的情景下,使用Vuex进行登录状态的统一管理就很方便。当然,虽然麻烦但也可以时刻在对应页面操作cookie。所以,状态管理不是必需的,所有状态管理能做的,都能用其它方式实现,但是状态管理提供了统一管理的地方,操作方便,也更加明确。但一些状态只是父组件和子组件共享,不推荐使用状态管理实现,而用$emitprops即可简单实现。

11.2Vuex的安装与基本应用

1.安装Vuex

VueRouter一样,将Vuex添加到项目中也有4种主要方法:本地独立版本方法、CDN方法、NPM方法以及命令行工具(VueCLI)方法。

2.项目文件中导入并显式地使用Vuex

使用VueCLI安装Vuex后,首先,在项目的/src/store/index.js文件中,导入Vuex模块,并创建一个store(仓库)。

然后,在项目主文件main.js中导入Vuex,并显式地使用Vue实例调用Vuex

    import { createApp } from 'vue'import App from './App.vue'import store from './store' //导入store目录中的index.js,Vuex的创建与配置在该文件中createApp(App).use(store).mount('#app')

    11.3Vuex的核心概念

    Vuex应用的核心是store,即仓库。store实际上就是一个容器,它包含应用中大部分的状态(state),与单纯的全局对象不同,主要有两点区别。

    1Vuex的状态存储是响应式的。也就是说,当Vue实例或组件从仓库store中读取状态时,若store中状态发生变化,那么相应的Vue实例或组件也会高效更新。

    2)用户不能直接更新store中的状态。更新的唯一途径是显式地提交mutation(类似于事件),以便跟踪每一个状态的变化。

    一个完整的store包含stategettersmutationsactionsmodules五大组成部分。

    11.3.1 Vuex中的state

    Vuex使用单一状态树,即使用一个对象包含了所有的应用层级状态,作为一个唯一的数据源而存在。也就是说,每个应用将仅包含一个仓库store实例。因此,需要状态跟踪(管理)的数据保存在Vuex选项的state选项内。

    1.在Vue 组件中通过computed计算属性获得 Vuex状态

    $storestore的区别

    l  $store是挂载在Vue 实例上的(即Vue.prototype),而组件也是一个Vue实例。在组件中可使用this访问原型上的属性,template拥有组件实例的上下文,可直接通过{{$store.state }}访问,等价于script 中的this.$store.state

    l  store是挂载到Vue上,为Vue的根实例;store引入后被注入到Vue上,成为Vue的原型属性,所以store是挂载到Vue上,为Vue的根实例;store引入后被注入到Vue上,成为Vue的原型属性,所以在script中通过store.state$store.state都可以访问。

    l  至于{{store.state}}script中的data需声明过store才可以访问。

    2.在Vue 组件中通过mapState()辅助函数获得Vuex 状态

    当一个组件需要获取多个状态时,将这些状态都声明为计算属性会有些重复和冗余。为解决这个问题,Vuex通过使用 mapState() 辅助函数帮助生成计算属性,减少按键次数。

    mapState() 辅助函数返回的是一个对象,用来获取多个状态。mapState()可以接收{}[]作为参数。

    {}参数为键值对形式参数,即key:valuekey为计算属性,value为函数,参数为store.state,返回需要的state

      computed: mapState({    // 箭头函数可使代码更简练    count: state => state.count,    // 传字符串参数 'count' 等同于 `state => state.count`    countAlias: 'count',    // 为了能够使用 `this` 获取局部状态,必须使用常规函数    countPlusLocalState(state) {      return state.count + this.localCount    }  })

      当映射的计算属性名称与state的子节点名称相同时,可以为mapState()传一个字符串数组参数。

      computed: mapState([

        // 映射 this.count 为 store.state.count

        'count'   //可以有多个state对象中属性,用逗号分隔

      ])

      3.对象展开运算符

        mapState()函数返回的是一个对象。如何将它与局部计算属性混合使用呢?通常,首先需要使用一个工具函数将多个对象合并为一个,然后将最终对象传给computed 属性。但自从有了对象展开运算符(…),可以极大地简化写法。computed: {  localComputed () { /* ... */ },  // 使用对象展开运算符将此对象混入到外部对象中  ...mapState({    // ...  })}

        app.vue

        app是从共享组件中读取数据,这里有两种方式,

        方法一

        this.$store.state.bookPress
        方法二
        ...mapState(['BISBN''bookPrice''bookAuthor']),注意这里的三个点的含义是打散的意思,我们看看下面的这个例子,.mapState数据赋值给变量S,然后在控制台打印,发现是个键值对,key是组件state里面的对象key。
        let mapState(['BISBN''bookPrice''bookAuthor'])

        ...mapState(['BISBN''bookPrice''bookAuthor']),最后就会变成

        BISBN:ƒ mappedState()

        bookPrice:ƒ mappedState()

        bookAuthorƒ mappedState()

          <template>
            <div>
              <h3>{{bookName}}</h3>
              <h3>作者:{{$store.state.bookAuthor}}</h3>
              <h3>出版社:{{$store.state.bookPress}}</h3>
              <h3>ISBN:{{$store.state.BISBN}}</h3>
              <h3>价格:{{$store.state.bookPrice}}</h3>
            </div>
            <hr/>
             <div>
              <h3>{{bookName}}</h3>
              <h3>作者:{{bookAuthor}}</h3>
              <h3>出版社:{{bookPress}}</h3>
              <h3>ISBN:{{BISBN}}</h3>
              <h3>价格:{{bookPrice}}</h3>
            </div>
          </template>
          <script>
          import { mapState } from 'vuex'
          export default {
            name: 'App',
            data() {//组件中的私有数据
              return {
                bookName : 'Vue.js '
              }
            },
            //使用计算属性获取store中的状态数据
            computed: {
              bookPress() {
                return this.$store.state.bookPress
              },
              //使用对象展开运算符获取store中的状态数据
              ...mapState(['BISBN', 'bookPrice', 'bookAuthor']),
            }
          }
          </script>
          <style>
          #app {
            font-family: Avenir, Helvetica, Arial, sans-serif;
            -webkit-font-smoothing: antialiased;
            -moz-osx-font-smoothing: grayscale;
            text-align: center;
            color: #2c3e50;
            margin-top: 60px;
          }
          </style>

          index.js

            import { createStore } from 'vuex'
            export default createStore
            ({  state: { BISBN : '9787302598503',   
             bookPrice : 99.8,    bookAuthor : '刘巍',    
             bookPress : '江西出版社'  }, 
              mutations: {  }, 
               actions: {  },  
               modules: {  }})

            main.js

              import { createApp } from 'vue'
              import App from './App.vue'
              import store from './store'
              createApp(App).use(store).mount('#app')

              11.3.2 Vuex中的getters

              在工程项目中,有时需要从 store.state 中派生出一些状态,如对列表进行过滤并计数,可以通过计算属性来实现,具体代码如下。

                computed: {
                  doneTodosCount () {
                    return this.$store.state.todos.filter(todo=> todo.done).length
                  }
                }

                Vuex允许在store中定义“getters(可以认为是 store 的计算属性)。getters可以接受state 作为其第一个参数,示例代码如下。

                  const store = createStore({
                    state: {
                      todos: [
                        { id: 1, text: '...', done: true },
                        { id: 2, text: '...', done: false }
                      ]
                    },
                    getters: {
                      doneTodos (state) {
                        return state.todos.filter(todo => todo.done)
                      }
                    } })

                  index.js

                    import { createStore } from 'vuex'
                    export default createStore({
                      state: {
                        BISBN : '9787302598503',
                        bookPrice : 99.8,
                        bookAuthor : '刘巍',
                        bookPress : '江西出版'
                      },
                      getters: {
                        //接受 state 作为其第一个参数
                        getBookPrice(state) {
                          return state.bookPrice
                        },
                        //接受其他 getters 作为第二个参数
                        getThreeTimesBookPrice(state, getters) {
                          return state.bookPrice + getters.getBookPrice * 2
                        }
                      },
                      mutations: {
                      },
                      actions: {
                      },
                      modules: {
                      }
                    })

                    getters程序流程图:

                    ①在21行中用插值语法读取计算属性的值.

                    ②计算梳理有个方法mapGetters里面有数组,数组里面就是方法名,系统就会调用store下面的index.JS文件,getters是默认的语法关键字.

                    ③getters方法就是从数据源state中获取数据,然后二次加工.

                    app.vue

                      <template>
                        <div>
                          <h3>{{bookName}}</h3>
                          <h3>作者:{{$store.state.bookAuthor}}</h3>
                          <h3>出版社:{{$store.state.bookPress}}</h3>
                          <h3>ISBN:{{$store.state.BISBN}}</h3>
                          <h3>价格:{{$store.state.bookPrice}}</h3>
                        </div>
                        <hr/>
                         <div>
                          <h3>{{bookName}}</h3>
                          <h3>作者:{{bookAuthor}}</h3>
                          <h3>出版社:{{bookPress}}</h3>
                          <h3>ISBN:{{BISBN}}</h3>
                          <h3>价格:{{bookPrice}}</h3>
                        </div>
                         <hr/>
                         <h3>getters访问</h3>
                         <h3>一本书花的钱:{{$store.getters.getBookPrice}}</h3>
                         <h3>三本书花的钱:{{$store.getters.getThreeTimesBookPrice}}</h3>
                         <h3>一本书花的钱:{{getBookPrice}}</h3>
                         <h3>三本书花的钱:{{getThreeTimesBookPrice}}</h3>
                      </template>
                      <script>
                      import { mapState } from 'vuex'
                      import { mapGetters } from 'vuex'
                      export default {
                        name: 'App',
                        data() {//组件中的私有数据
                          return {
                            bookName : 'Vue.js 3'
                          }
                        },
                        //使用计算属性获取store中的状态数据
                        computed: {
                          bookPress() {
                            return this.$store.state.bookPress
                          },
                          //使用对象展开运算符获取store中的状态数据
                          ...mapState(['BISBN', 'bookPrice', 'bookAuthor']),
                          ...mapGetters(['getBookPrice', 'getThreeTimesBookPrice'])//混入计算属性
                        }
                      }
                      </script>
                      <style>
                      #app {
                        font-family: Avenir, Helvetica, Arial, sans-serif;
                        -webkit-font-smoothing: antialiased;
                        -moz-osx-font-smoothing: grayscale;
                        text-align: center;
                        color: #2c3e50;
                        margin-top: 60px;
                      }
                      </style>

                      main.js

                        import { createApp } from 'vue'
                        import App from './App.vue'
                        import store from './store'
                        createApp(App).use(store).mount('#app')

                        11.3.3 Vuex中的mutations

                        更改 Vuex 的 store 中的状态的唯一方法是提交 mutations。每个 mutation 都有一个字符串的事件类型 (type)和一个回调函数 (handler)。这个回调函数就是实际进行状态更改的地方,并且它会接受 state 作为第一个参数。(其实简单的理解就是state的数据不能直接修改,需要通过mutations里面的方法去修改数据源state的数据)

                        const store = createStore({
                        
                          state: {
                        
                            count: 1
                        
                          },
                        
                          mutations: {
                        
                            increment (state) {  // increment为事件类型type,state为参数
                        
                              // 变更状态
                        
                              state.count++
                        
                            }
                        
                          }
                        
                        })

                        不能直接调用一个 mutation 处理函数。这个选项更像是事件注册:“当触发一个类型为 increment 的 mutation 时,调用此函数。”要唤醒一个 mutation 处理函数,需要以相应的 type 调用 store.commit()方法。store.commit('increment')

                        11.3.4 Vuex中的actions

                        actions 类似于 mutations,不同在于以下两点。

                        l  actions提交的是 mutations,而不是直接变更状态。

                        l  actions可以包含任意异步操作。

                        actions中的方法需要使用store.dispatch()方法调用。action函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此可以调用 context.commit() 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters

                        一句话解释:action就是异步请求,比如我调用一个接口,我不会等接口结果,就处理后面的代码,等接口返回数据的时候,我重新渲染页面。

                        app.vue

                        <template>
                          <div>
                              <h3>书名:{{bookName}}</h3>
                              <h3>出版社:{{$store.state.bookPress}}</h3>
                              <h3>作者:{{$store.state.bookAuthor}}</h3>
                              <h3>原价:{{bookPrice}}</h3>
                          </div>
                          <hr/>
                          <my-add></my-add>
                          <hr/>
                          <my-reduce></my-reduce>
                        </template>
                        <script>
                        import { mapState } from 'vuex'
                        import AddBookPrice from './components/AddBookPrice.vue'
                        import ReduceBookPrice from './components/ReduceBookPrice.vue'
                        export default {
                          name: 'App',
                          computed: {
                              ...mapState(
                              //混入计算属性
                              ['bookName','bookPrice']
                             )
                          },
                          components: {//定义子组件
                            'my-add': AddBookPrice,
                            'my-reduce': ReduceBookPrice
                          }
                        }
                        </script>
                        <style>
                        #app {
                          font-family: Avenir, Helvetica, Arial, sans-serif;
                          -webkit-font-smoothing: antialiased;
                          -moz-osx-font-smoothing: grayscale;
                          text-align: center;
                          color: #2c3e50;
                          margin-top: 60px;
                        }
                        </style>

                        index.js

                        import { createStore } from 'vuex'
                        export default createStore({
                          state: {
                            BISBN : '9787302598503',
                            bookPrice : 99.8,
                            bookAuthor : '刘巍',
                            bookPress : '江西出版社',
                            bookName : 'Vue.js 3'
                          },
                          getts: {
                          },
                          mutations: {
                            addBookBy10(state) {
                              state.bookPrice = state.bookPrice + 10
                            },
                            addBookByNum(state, num) {
                              state.bookPrice = state.bookPrice + num
                            },
                            reduceBookBy10(state) {
                              state.bookPrice = state.bookPrice - 10
                            },
                            reduceBookByNum(state, num) {
                              state.bookPrice = state.bookPrice - num
                            },
                          },
                          actions: {
                            //同步增加
                            addBookBy10Action(context) {
                              //执行mutations中的addBookBy10
                              context.commit('addBookBy10')
                            },
                            //同步减少,step为参数
                            reduceBookByNumAction(context, step) {
                              //执行mutations中的reduceBookByNum
                              context.commit('reduceBookByNum', step)
                            },
                            //异步增加
                            addBookBy10ActionAsync(context) {
                              setInterval(() => {
                                context.commit('addBookBy10')
                              }, 1000);
                            },
                            //异步减少,step为参数
                            reduceBookByNumActionAsync(context, step) {
                              setInterval(() => {
                                context.commit('reduceBookByNum', step)
                              }, 1000);
                            }
                          },
                          modules: {
                          }
                        })

                        main.js

                        import { createApp } from 'vue'
                        import App from './App.vue'
                        import store from './store'
                        createApp(App).use(store).mount('#app')
                        
                                        

                        相关文章:

                      • Vue2+Vue3 1~45集学习笔记
                      • QT初级使用教程
                      • 国内常用镜像源地址汇总及使用示例
                      • Oracle 数据库系统全面详解
                      • 如何在Windows服务器上搭建RADIUS认证服务器,有哪些开源方案和付费解决方案
                      • AutoDIR: Automatic All-in-One Image Restoration with Latent Diffusion 论文阅读 ECCV
                      • Ubuntu 22.04 上安装 VS Code
                      • 腾讯云大模型知识引擎驱动DeepSeek满血版能源革命大模型:架构、优势与产业变革
                      • linux下DLT Daemon和DLT viewer的安装
                      • 网页版五子棋项目的问题处理
                      • Spring Boot 非web应用程序
                      • 2025年3月29日(matlab -ss -lti)
                      • 宝塔面板面试内容整理-Web管理功能
                      • 鸿蒙篇:vp、fp、px
                      • MCP - 使用 BlenderMCP 让 Claude AI 控制你的 Blender 模型创作
                      • ARMv7的MPU
                      • 《非暴力沟通》第十二章 “重获生活的热情” 总结
                      • Linux--基础IO
                      • HTTP事务描述
                      • 超级创新思路:基于元学习MTGCN-Attention-Transformer的时间序列预测模型(Python\matlab实现)
                      • 东乡哪里有做网站/seo成功的案例和分析
                      • 南宁网站建设公司哪里/引擎优化是什么意思
                      • 北京网站设计我选柚米/怎么自己做一个网页
                      • 做外贸网站那个平台好/专业提升关键词排名工具
                      • 网站设计基本原则/做网站优化推广
                      • asp动态网站开发案例教程 pdf/指数基金有哪些