Vue-Vuex

发布时间 2023-12-05 23:54:51作者: 一笔带过

Vuex

vuex 是专为vue.js应用程序开发的管理模式,它采用集中式储存管理应用的去全部组件状态,并以响应的规则邦正状态可以以一种可预测的方式变化


主要管理数据

使用vuex的时机,vuex相当于商店,谁都可以取买卖东西
当两个组件没有关系的情况下
1.如果项目中型或者大型,不推荐 使用 父子组件传值
2.中央事件总线可以推荐使用 中型项目 设置bus 使用emit 和 on 实现
项目足够大的时候 中央事件总线不可以,太臃肿
3.使用vuex 类似一个单例的对象 vuex管理状态(想共享的状态(数据)) 大型
共享的数据放到vuex
加入购物车 - vuex 中的Actions(异步的)中的方法 -提交-mutations(同步的)-修改- state:{ 共享的数据 状态} - 渲染- 需要使用这个数据的组件中
登录注册,购物车 ,权限控制,组件之间不好通信的时候就会使用vuex
中大型项目中,组件之间不好通信 就会使用vuex
修改数据的唯一方法 就是actions方法中提交mutations方法


vuexAPI:https://vuex.vuejs.org/zh/

目录

store/index.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {  // 状态(属性) 也就是当前存放数据的地方
  },
  getters: { // 计算属性方法
  },
  mutations: { // 同步方法 由它进行对状态的值进行修改(必须是它)
  },
  actions: { // 异步方法  异步方法由它调用当前的同步方法
  },
  modules: { // 模块嵌套方法
  }
})

在main.js 对vuex进行挂载
import Vue from 'vue'
import App from './App.vue'
import store from './store'

Vue.config.productionTip = false

new Vue({
  store,
  render: h => h(App)
}).$mount('#app')

使用步骤

1.在state对像 中设置公共的状态参数
2.在 mutations中设置一个函数负责对这个参数 进行变化和修改(设置的函数中需要接受参数state对象)
3. 在actions 中设置一个函数,使用commit进行执行在mutations中函数
4.在对应的组件中设置的按钮中,绑定一个函数,函数内容需要执行actions中的设置的函数

vuex的基本使用

在组件中使用vuex中的state内数据

export default new Vuex.Store({
  state: {
    count:10,
  },
....
}

// 使用this.$store 调用vuex中的内容
this.$store.state.count 

在组件中使用调用vuex中getters内方法

export default new Vuex.Store({
  state: {
    count:10,
  },
  getters: {
    getCount(state,getters){
     // 接受state对象就是当前vuex状态
     // 接受getters对象就是当前计算属性本身,可以通过getters调用内部的方法 getters.getCount   
      console.log(state)
      return state.count+10
    }
  },
  .....
  }
                              
// 在组件中进行调用当前方法
this.$store.getters.getCount // 可以直接调用
or
computed: { // 使用vue中的计算属性监听
  count() {  // vuex计算属性的使用
      return this.$store.getters.getCount
    }
}

在组件中的使用mutation同步方法

export default new Vuex.Store({
    state: {
        count:10,
    },
    getters: {
    },
    mutations: { // 同步方法
        getInfo(state,val){
            // state 状态对象
            // val 是调用是提交的方法
            state.count += val // 对状态中的count+val的操作
        }
    },
    .....
}

在组件中进行调用:
  methods:{
    show(){
      commit('mutations中的方法名','传入的变量')
      this.$store.commit('getInfo',10)
    }
  },
 
只能进行同步操作
每个mutation执行完成后都会对应到一个新的状态变更,这样devtools就可以打个快照存下来,然后就可以实现 time-travel 了。
如果mutation支持异步操作,就没有办法知道状态是何时更新的,无法很好的进行状态的追踪,给调试带来困难

在组件中的使用actions异步方法

export default new Vuex.Store({
  state: {
    count:10,
  },
  getters: {
  },
  mutations: { // 同步方法
    getInfo(state,val){
      // state 状态对象
      // val 是调用是提交的方法
      state.count += val // 对状态中的count+val的操作
    }
  },
  actions: { // 异步
    getInfo({commit},val){
      // val 是调用者传入的参数
      commit('getInfo',val) // 通过解构出来的commit方法调用mutations中的同步方法
    }
  },
  modules: {
  }
})


组件调用:
通过$store.dispatch调用actions的方法
this.$store.dispatch('getInfo',10)


/*
解构的内容为:
obj是一个对象 {getters: {…}, state: {…}, rootGetters: {…}, dispatch: ƒ, commit:}
可以通过解构的方式获取其中的对象,每个对象对应着 是当前的vuex状态对象的方法 dispatch是当前启动actions中的方法
*/

actions与mutations为什么要使用或区别

mutations: 声明的方法是同步的,就是页面的更新,不需要从后端获取请求 
actions:声明的方法时异步的(一旦异步就需要使用actions的方法)需要后端发起请求获取或者怎么样
两个之间的区别在哪里
修改状态(state对象的参数)的唯一方法就是提交commit


触发dispatch,就是触发actions中的函数方法
this.$store.dispatch('func') // 异步的话就使用dispatch
同步直接使用mutations中的方法就行
this.$store.commit('func') // 提交



异步:实时更新,只要你操作就会先对你的值进行更新,然后在存储到数据库中
同步:当你点击对你的值进行更新时,需要先存入数据库,在进行显示
案例:

export default new Vuex.Store({
    state: {
        count: 10,
    },
    getters: {},
    mutations: { // 同步方法
        getInfo(state) {
            setTimeout(() => {
                state.count++
            }, 1000)
        }
    },
    actions: { // 异步
        getInfo({commit}) {
            setTimeout(() => {
                commit('getInfo')
            }, 1000)
        }
    },
    modules: {}
})

组件内
<template>
  <div id="app">
    <div>{{this.$store.state.count}}</div>
    <button @click="show1">异步+1操作</button>
    <button @click="show2">同步+1操作</button>
  </div>
</template>

<script>


export default {
  name: 'App',
  components: {},
  data(){
    return{
    }
  },
  methods:{
   show1(){
    this.$store.dispatch('getInfo')
   },
    show2(){
     this.$store.commit('getInfo')
    }
  },

}
</script>

<style lang="scss">

</style>

需要使用谷歌的vue组件进行查看
使用同步方式时:
	虽然页面显示的时增加的正确数值,但是在vue组件中监控的数值永远比页面中 少1
 
使用异步的方式:
	页面显示的数值与监控的数值是相同的。

辅助函数的使用

import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'

mapState 辅助获取状态中的参数
mapMutations,mapActions 辅助获取同步异步的方法
mapGetters 获取计算属性中的方法
<template>
    <div id="app">
        <!--vuex参数的渲染-->
        <p>{{ count }}</p>
        <p>{{ getCount }}</p>
        <button @click="getInfo">点击</button>
    </div>
</template>

<script>
import {mapActions, mapState, mapGetters, mapMutations} from 'vuex'

export default {
    name: 'App',
    components: {},
    data() {
        return {}
    },
    methods: {
        ...mapActions(['getInfo']), // 执行actions 中的方法
        ...mapMutations(['getInfo']) //执行 mutations 中的方法
    },
    computed: {
        ...mapState(['count']), // mapState作用就是取状态的值
        ...mapGetters(['getCount']) // mapGetters取vuex中的计算属性
    }
}
</script>

vuex中modules嵌套使用

import Vue from 'vue'
import Vuex from 'vuex'
import a from '@/store/xx/a' //导入
import b from '@/store/xx/b'

Vue.use(Vuex)

export default new Vuex.Store({
    state: {
        terr:1000
    },
    getters: {},
    mutations: {},
    actions: {},
    modules: {
        // 模块当vuex 数据过多时,可以使模块进行处理
        a, b //挂载模块
    }
})

子1

export default {
    namespaced: true, // 命名空间后,就会根据注册的名字调整当前的路径,这样的话就会进行分开
    state: {
        a: '我是a节点',
    },
    getters: {
        getCount(state, getters, rootState) {
            // 这个state归属于当前这个模块的state
            // getters 是当前的getters对象
            // rootState 属于根节点对象:也就是当前模块的上级对象
            return rootState.b.b // 返回根节点的状态(同时也能通过根节点获取其他节点的状态和方法)
        }
    },
    mutations: {
        show(state) {
            // 这个state归属于当前这个模块的state
            console.log('sb')
        }
    },
    actions: {
        show({commit, state, rootState}) {
            // 这个obj对象中存放着 {getters: {…}, state: {…}, rootGetters: {…}, dispatch: ƒ, commit: ƒ,}
            // 可以通过解构获取出来
            // commit,state,rootGetters : commit:属于执行mutations的方法
            // state: 这个state归属于当前这个模块的state
            // rootState 是根节点对象,也就是当前模块的上级对象 可以通过它获取父节点的参数 和其他节点的参数和方法
            //commit('show')
            commit('b/show',{root:true}) // 使用向直接调用b模块的方法 需要传入 一个参数{root:true}开启权限
        }
    },
}

子2

export default {
    namespaced: true, // 命名空间后,就会根据注册的名字调整当前的路径,这样的话就会进行分开
    state: {
        b: '我是b节点'
    },
    getters: {},
    mutations: {},
    actions: {
        shows() {
            console.log('b节点')
        }
    },
}

在组件中使用

<template>
    <div id="app">
        <!--vuex参数的渲染-->
        <p>{{ numShow }}</p>
        <p>{{ a }}</p>
        <p>{{getCount}}</p>

        <button @click="show">点击</button>
    </div>
</template>

<script>
import {mapActions, mapState, mapGetters, mapMutations} from 'vuex'

export default {
    name: 'App',
    components: {},
    data() {
        return {}
    },
    methods: {
        shows() {
            // 不是用辅助函数调用a模块下的actions中的show方法
            this.$store.dispatch('a/show') //相当于找到路径
        },
        // 使用辅助函数调用a模块下的actions中的show方法
        ...mapActions('a',['show']) // 参数1:模块a 参数2对应的函数方法
    },
    computed: {
        // 使用辅助函数取到a模块和b模块下的状态值
        ...mapState('a', ['a']), // 参数1:代表模块 参数2:代表状态变量
        ...mapState('a', ['b']),
        numShow() {
            return this.$store.state.a.a // 不是使用辅助函数
        },
        ...mapGetters('a',['getCount']) // 使用辅助函数 a模块下的计算方法
    }
}
</script>