草庐IT

【Vue】Vuex状态管理器的使用

早睡早起长头发 2023-12-30 原文

目录

一、Vuex是什么?

二、什么时候使用Vuex?

三、Vuex的核心概念和API

1.state

2.mutations

3. actions

4. getters

5. modules

四、Vuex的运作流程 

五、应用举例 

1.安装

2.创建store

3.在main.js文件中使用store

4.创建Home.vue组件

5.在App.vue中导入Home.vue

六、vuex中各种辅助函数的用法,可以使我们更加方便的运用vuex

1.  …mapState

2.  …mapGetters

3.  …mapMutations:使用辅助函数后载荷的传参,直接在调用的地方进行传参便可

4.  …mapActions

 5. 修改后Home.vue组件


一、Vuex是什么?

  • Vuex在Vue项目开发时使用的状态管理工具。简单来说,就是对Vue的应用中多个组件的共享状态进行集中式的管理(读/写)
  • Vuex实现了一个单向数据流,在全局拥有一个State存放数据,当组件要更改State中的数据时,必须通过Mutation进行,Mutation同时提供了订阅者模式供外部插件调用获取State数据的更新。
  • 而当所有异步操作(常见于调用后端接口异步获取更新数据)或批量的同步操作需要走Action,但Action也是无法直接修改State的,还是需要通过Mutation来修改State的数据。最后,根据State的变化,渲染到视图上

二、什么时候使用Vuex?

  • 不适用场景:小型简单应用,用 Vuex 是繁琐冗余的,更适合使用简单的store模式
  • 适用场景: 构建一个中大型单页应用,可能会考虑如何更好地在组件外部管理状态,即多个组件共享状态
  • 多个视图依赖于同一状态:此时传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。
  • 来自不同视图的行为需要变更同一状态:此时采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝,通常会导致无法维护的代码
  • 在这些情况下就适合用Vuex进行全局单例模式管理

三、Vuex的核心概念和API

流程:View -> Actions -> Mutations -> State -> View

 

1.state

  • vuex 管理的状态对象
  • 它应该是唯一的

        const state = {
        xxx: initValue
        }


2.mutations

  • 包含多个直接更新 state 的方法(回调函数)的对象
  • 谁来触发: action 中的 commit(‘mutation 名称’)或者在组件中通过this.$store.commit(‘xxx’,params)使用。这个和组件中的自定义事件类似
  • 只能包含同步的代码, 不能写异步代码

        const mutations = {
                xxx(state, {data1}) {
                // 更新 state 的某个属性
                }
        }


3. actions

  • 提交 mutation,异步操作。包含多个事件回调函数的
  • 通过执行: commit()来触发 mutation 的调用, 间接更新 state
  • 谁来触发: 组件中通过this.$store.dispatch(‘action 名称’, data1)
  • 可以包含异步代码(axios)

        const actions ={
                zzz ({commit, state}, data1)
                commit(‘xxx’, {data1})
                }
        }


4. getters

  • 对数据获取之前的再次编译,可以理解为state的计算属性
  • 谁来读取: 组件中: this.$store.getters.xxx

        const getters ={
                xxx (state) {
                return …
                }
        }


5. modules

  • 包含多个 module:store的子模块,为了开发大型项目,方便状态管理而使用的,即将store分割为模块,使store对象不会太臃肿。
  • 一个 module 是一个 store 的配置对象
  • 与一个组件(包含有共享数据)对应

四、Vuex的运作流程 

 

流程详解:

  1. 在组件(页面)中,通过dispatch()或mapActions()这个函数分发给actions的函数去处理。
  2. actions的函数可以与后台交互,也可以通过 commit() 提交给mutations去处理。
  3. mutations 可以直接与devtool(如本地存储工具 → 在实例代码中的utils里的storageUtils.js)交互与直接更新state(数据状态)。
  4. 如果有计算属性(get函数写在getters里面),则状态通过getters的$store.getters()或mapGetters()来更新组件;反之就通过$store.state()或者mapState()的方式来更新组件。

五、应用举例 

1.安装

        npm i vuex -S

2.创建store

        store:src/store/index.js

import {createStore} from "vuex";
export default createStore({
    //state全局存储数据的对象
    state:{
        count:0,
        age:0
    },
    //计算属性(可选的):用于获取state属性的值。
    //(1)若定义了getters:获取属性值的方法是$store.getters()或mapGetters()
    //(2)若没有定义getters,获取state属性值的方法是:$store.state()或者mapState()
    getters:{
        getterAge:(state)=>{  //state是原来的状态
            return state.age = 25  //return返回的是新的状态
        }
    },
    //mutations:用于修改state状态值,定义的函数必须是同步的
    mutations:{
        addCount(state,obj){ //state是原来的state,obj是调用该方法时传入的对象
            return state.count += obj.num
        },
        subCount(state,obj){
            return state.count -=obj.num
        }
    },
//    actions:通过动作的提交,来调用mutations中方法,修改state属性
    actions:{
    //    异步加法函数
        addCountAsyn(context){//context:表示上下文环境,就派发动作的对象(组件)
            setTimeout(()=>{
                context.commit('addCount',{
                    num:1
                })
            },3000)
        },
    //    异步减法函数
        subCountAsyn(context){
            setTimeout(()=>{
                context.commit('subCount',{
                    num:1
                })
            },3000)
        }
    }
})

3.在main.js文件中使用store

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import store from './store/index'

const app= createApp(App);
app.use(store)

app.mount('#app')

4.创建Home.vue组件

<template>
  <div>
    <h2>通过getter获得计算后的年龄:{{ getterAge }}</h2>
    <p>Count:{{ count }}</p>
    <button @click="handlerAdd()">加1</button>
    <button @click="handlerSub()">减1</button>
    <button @click="handlerAddAnys()">异步增加(2s后执行)</button>
    <button @click="handlerSubAnys()">异步减少(2s后执行)</button>
  </div>
</template>

<script>
export default {
  name: "Home",
  computed: {
    count(){
      return this.$store.state.count
    },
    getterAge(){
      return this.$store.getters.getterAge
    }
   },
  methods: {
    handlerAdd(){
      this.$store.commit("addCount",{
        num: 1
      })
    },
    handlerSub(){
      this.$store.commit("subCount",{
        num: 1
      })
    },
    handlerAddAnys(){
      this.$store.dispatch('addCountAsyn')
    },
    handlerSubAnys(){
      this.$store.dispatch('subCountAsyn')
    }
   }
}
</script>

<style scoped>

</style>

5.在App.vue中导入Home.vue

import Home from './components/Home.vue'
<template>
  <img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
  <Home/>
</template>

六、vuex中各种辅助函数的用法,可以使我们更加方便的运用vuex

1.  …mapState

count(){
     return this.$store.state.count
},
     等价于
...mapState([
  'count'
]),

2.  …mapGetters

count(){
     return this.$store.state.count
},
     等价于
...mapState([
  'count'
]),

3.  …mapMutations:使用辅助函数后载荷的传参,直接在调用的地方进行传参便可

handlerAdd(){
  this.$store.commit("addCount",{
    num: 1
  })
},
handlerSub(){
  this.$store.commit("subCount",{
    num: 1
  })
},
等价于
...mapMutations({
  handlerAdd: 'addCount',
  handlerSub: 'subCount'
})
     

4.  …mapActions

handlerAddAnys(){
  this.$store.dispatch('addCountAsyn')
},
handlerSubAnys(){
  this.$store.dispatch('subCountAsyn')
}
等价于
...mapActions({
  handlerAddAnys: 'addCountAsyn',
  handlerSubAnys: 'subCountAsyn'
})

修改上例中的Home.vue组件

 

 5. 修改后Home.vue组件

<template>
<div>
  <h3>通过Getters获取age:{{ getterAge }}</h3>
  <p>Count:{{ count }}</p>
  <button @click="handlerAdd({num:1})">同步加一</button>
  &nbsp; &nbsp; &nbsp; &nbsp;
  <button @click="handlerSub({num:1})">同步减一</button>
  &nbsp; &nbsp; &nbsp; &nbsp;
  <button @click="handlerAddAsyn">异步加一(3s后执行)</button>
  &nbsp; &nbsp; &nbsp; &nbsp;
  <button @click="handlerSubAsyn">异步减一(3s后执行)</button>
</div>
</template>
<script>
import  { mapState,mapGetters,mapMutations,mapActions } from 'vuex'
export default {
  name: "Home",
  computed: {
    // count() { //使用非getters方法获取state的count属性值
    //   return this.$store.state.count
    // },
    ...mapState(['count']),

  //   getterAge() {//使用getters方法获取state的age属性
  //     return this.$store.getters.getterAge
  //   }
    ...mapGetters(['getterAge'])
   },

  methods: {
    // handlerAdd() {//同步加一
    //   this.$store.commit('addCount', {num: 1});//通过commit提交动作:addCount,给mutation
    // },
    // handlerSub() {//同步减一
    //   this.$store.commit('subCount', {num: 1})
    // },
    ...mapMutations({
      handlerAdd:'addCount',
      handlerSub:'subCount'
    }),

    // handlerAddAsyn() {//异步加一
    //   this.$store.dispatch('addCountAsyn');//通过dispatch方法将动作派发给action,再由action提交给mutation
    // },
    // handlerSubAsyn() {//异步加一
    //   this.$store.dispatch('subCountAsyn');//通过dispatch方法将动作派发给action,再由action提交给mutation
    // }
    ...mapActions({
      handlerAddAsyn:'addCountAsyn',
      handlerSubAsyn:'subCountAsyn'
    })
  }
}
</script>

<style scoped>

</style>

有关【Vue】Vuex状态管理器的使用的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  6. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  7. ruby - i18n Assets 管理/翻译 UI - 2

    我正在使用i18n从头开始​​构建一个多语言网络应用程序,虽然我自己可以处理一大堆yml文件,但我说的语言(非常)有限,最终我想寻求外部帮助帮助。我想知道这里是否有人在使用UI插件/gem(与django上的django-rosetta不同)来处理多个翻译器,其中一些翻译器不愿意或无法处理存储库中的100多个文件,处理语言数据。谢谢&问候,安德拉斯(如果您已经在ruby​​onrails-talk上遇到了这个问题,我们深表歉意) 最佳答案 有一个rails3branchofthetolkgem在github上。您可以通过在Gemfi

  8. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  9. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  10. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

随机推荐