欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 能源 > Vue 入门到实战 十一 Vuex

Vue 入门到实战 十一 Vuex

2025/4/3 7:02:53 来源:https://blog.csdn.net/wl8511/article/details/146762436  浏览:    关键词: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中的addBookBy10context.commit('addBookBy10')},//同步减少,step为参数reduceBookByNumAction(context, step) {//执行mutations中的reduceBookByNumcontext.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')

                        版权声明:

                        本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

                        我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

                        热搜词