Vue 状态管理 (vuex+非vuex方式)

本文介绍了在Vue应用中管理状态的两种方式:非Vuex方式和使用Vuex。非Vuex方式通过Vue的provide/inject实现组件间状态传递,而Vuex则提供了一个集中式的状态管理模式,包括state、mutation、getter、action等核心概念。文章通过代码演示展示了如何安装、配置和使用Vuex,以及如何通过模块化管理和命名空间来组织复杂的状态。
摘要由CSDN通过智能技术生成

目录

非vuex方式

代码演示

Vuex 

安装

State 单一状态树

代码演示

 Mutation

代码演示

 Getter

代码演示

Action

代码演示

辅助函数

代码演示

module

代码演示

命名空间


非vuex方式

代码演示

 index.js

//状态集中管理
//数据实现响应式
//使用场景: 权限管理 路径 对用户进行权限限制

import { reactive } from "vue"

//ref-->字符串,数字 reactive-->对象中存储
const store={
  //定义状态
  state:reactive({
    state:"未登入"
  }),
  updateState(){
    this.state.state="已登入"
  }
}
//在App组件通过provide提供
export default store

App.vue

<script>
 //vue3设置状态管理
 //provide/inject 跨级通信
 import User from "./views/User.vue"
 import store from "./store"
 export default{
  provide:{
    store,
  },
  components: {
    User
  }
 }
</script>
<template>
<User/>
</template>
<style>
</style>

User.vue

<template>
  <h2>用户页面</h2>
  <div>
    {{store.state.state}}
    <br>
    <button @click="updateState">改变状态</button>
  </div>
</template>
<script>
export default{
  inject: ["store"],
  methods:{
    updateState(){
      this.store.updateState();
    }
  }
}
</script>

 运行结果

点击按钮前

点击按钮后

Vuex 

官网

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

什么情况下应该使用 Vuex?

Vuex 可以帮助我们管理共享状态,并附带了更多的概念和框架。

如果您的应用够简单,您最好不要使用 Vuex。一个简单的 store 模式就足够您所需了。

如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。

安装

npm

npm install vuex@next --save

确认是否安装完成

State 单一状态树

Vuex 使用单一状态树——是的,用一个对象就包含了全部的应用层级状态。至此它便作为一个“唯一数据源 (SSOT)”而存在。这也意味着,每个应用将仅仅包含一个 store 实例。单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。

代码演示

store index.js

//状态集中管理
//数据实现响应式
//使用场景: 权限管理 路径 对用户进行权限限制
import { createStore } from "vuex"

//创建store实例
const store=createStore({
  //存储的单一状态 存储基本数据
 state(){
   return{
    name:'state简单使用'
   }
 }
})

export default store

 

main.js

import { createApp } from 'vue'
import App from './App.vue'
//不用写到index 也可以 会默认指到 鼠标移到会显示出: module "d:/桌面/vue_learn/vueLearn/src/router/index"
import router from './router'
import store from './store'

const app=createApp(App)
//挂载仓库
app.use(store)
app.use(router)
app.mount('#app')

App.vue

<template>
  <h2>{{$store.state.name}}</h2>
</template>
<script>
export default{

}
</script>

运行结果

 Mutation

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。

在 Vuex 中,mutation 都是同步事务

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

代码演示

store index.js

//状态集中管理
//数据实现响应式
//使用场景: 权限管理 路径 对用户进行权限限制
import { createStore } from "vuex"

//创建store实例
const store = createStore({
  //存储的单一状态 存储基本数据
  state() {
    return {
      name: 'state简单使用'
    }
  },
  mutations: {
    //state表示上面state返回的对象 value表示传过来的参数
    changeName(state, value) {
      state.name = 'mutations简单使用';
      console.log('value表示传过来的参数===>'+value);
    }
  }
})

export default store

App.vue

<template>
  <h2>App.vue======>{{ $store.state.name }}</h2>
  <br>
  <User/>
  <br>
  <button @click="changeName('传入的字符')">改变Name</button>
</template>
<script>
import User from './views/User.vue'
export default {
  methods:{
    changeName(value){
      //通过store.commit 方法改变触发对应函数状态改变
      this.$store.commit('changeName',value);
    }
  },
  components:{
   User
  }
};
</script>

User.vue

<template>
  <h2>用户页面</h2>
  <h2>User.vue======>{{ $store.state.name }}</h2>
</template>
<script>
</script>

运行结果 

 Getter

store 的计算属性

代码演示

store index.js

//状态集中管理
//数据实现响应式
//使用场景: 权限管理 路径 对用户进行权限限制
import { createStore } from "vuex"

//创建store实例
const store = createStore({
  //存储的单一状态 存储基本数据
  state() {
    return {
      name: 'state简单使用'
    }
  },
  //可使用在 state的状态需要过滤或者其他的操作
  //可作为store中的计算属性
  getters:{
    reverName(state){
     return state.name.split('').reverse().join('');
    },
    //getters 参数 表示当前store中的getters对象
    reverNameLength(state,getters){
      return getters.reverName.length;
    }
  }
})

export default store

App.vue

<template>
  <h2>{{$store.getters.reverName}}</h2>
  <br>
  <h2>{{$store.getters.reverNameLength}}</h2>
</template>
<script>

</script>

运行结果 

Action

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。

代码演示

后端接口 更多完整获取后端数据方法

 store index.js

//状态集中管理
//数据实现响应式
//使用场景: 权限管理 路径 对用户进行权限限制
import axios from "axios";
import { createStore } from "vuex"

//创建store实例
const store = createStore({
  //存储的单一状态 存储基本数据
  state() {
    return {
      redisKey: ''
    }
  },
  mutations:{
    //将actions获取的数据 放入state中
   updateRedisKey(state,value){
      state.redisKey=value
   }
  },
  actions:{
    //context:与store实例具有相同的属性和方法的对象
    //payload store.dispatch传来的参数
    getRedisKey(context,payload){
      console.log('======context====');
      console.log(context);
      console.log('======payload====');
      console.log(payload);
      //获取后端数据
      axios.get('api/user/toCreateVerifyImg').then(res=>{
        console.log('后端数据');
        console.log(res);
        //提交到mutations
        context.commit('updateRedisKey',res.data.data.redisKey);
      })
    }
  }
})

export default store

App.vue

<template>
  <h2>{{$store.state.redisKey}}</h2>
  <br>
  <button @click="updateRedisKey">更新redisKey数据</button>
</template>
<script>
export default{
  methods:{
    updateRedisKey(){
      //在组件中分发 Action
      this.$store.dispatch('getRedisKey','dispatch传入数据了')
    }
  }
}
</script>

运行结果 

辅助函数

当一个组件需要获取多个状态的时候,将这些状态都声明会有些重复和冗余。为了解决这个问题,我们可以使用mapActions, mapGetters, mapMutations, mapState 辅助函数帮助我们,让你少按几次键

代码演示

store index.js

//状态集中管理
//数据实现响应式
//使用场景: 权限管理 路径 对用户进行权限限制
import { createStore } from "vuex"
//创建store实例
const store = createStore({
  //存储的单一状态 存储基本数据
  state() {
    return {
      userAge: 18,
      name:'state简单使用'
    }
  },
  getters: {
    changeAge(state) {
      return state.userAge = 19;
    }
  },
  mutations: {
    //state表示上面state返回的对象 value表示传过来的参数
    changeName(state) {
      state.name = 'mutations简单使用';
    }
  }
})
export default store

App.vue

<template>
  <h2>{{ msg }}</h2>
  <br />
  <h2>{{ userAge }}</h2>
  <br />
  <h2>{{ changeAge }}</h2>
  <br />
  <h2>{{ name }}</h2>
  <br />
  <button @click="changeName">改变name</button>
</template>
<script>
import { mapActions, mapGetters, mapMutations, mapState } from "vuex";

export default {
  data() {
    return {
      msg: "hello world",
    };
  },
  computed: {
    changeMsg() {
      return (this.msg = "你好 世界");
    },
    //辅助函数 减少代码冗余
    ...mapState(["userAge", "name"]),
    ...mapGetters(["changeAge"]),
  },
  methods: {
    changeName() {
      this.changeName();
    },
    ...mapMutations(["changeName"]),
    // ...mapActions([''])
  },
};
</script>

运行结果 

module

官网

为什么要有module?

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。

为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割

代码演示

 store user index.js

const user={
    //可通过$store.state.模块名.状态名获取
    state(){
        return{
            userName:"张三"
        }
    },
    //可通过$store.getters直接获取
    getters:{
        //state 局部状态
      changeName(state,getters,rootState){
        //store实例的getters对象
         console.log(getters);
         //rootState 获取根节点实例的state状态
         console.log(rootState);
         return state.userName='李四';
      }
    }
    //其他 mutations和action等等差不多操作 详情可看官网
}
export default user

store index.js

//状态集中管理
//数据实现响应式
//使用场景: 权限管理 路径 对用户进行权限限制
import { createStore } from "vuex"
import user from './user/index'
//创建store实例
const store = createStore({
  //存储的单一状态 存储基本数据
  state() {
    return {
      userAge: 18
    }
  },
  getters: {
    changeAge(state, getters) {
      return state.userAge = 19;
    }
  },
  modules: {
    user
  }
})
export default store

App.vue

<template>
  <!-- 普通访问 -->
  <h2>{{$store.state.userAge}}</h2>
  <br>
  <!-- 模块化的访问形式 -->
  <h2>{{$store.state.user.userName}}</h2>
  <br>
  <button @click="changeUserName">更新userName数据</button>
</template>
<script>
export default{
  methods:{
    changeUserName(){
      this.$store.getters.changeName;
    }
  }
}
</script>

运行结果

 命名空间

命名空间

如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。

代码演示

store user index.js

const user = {
    //开启命名空间
    namespaced: true,
    //可通过$store.state.模块名.状态名获取
    state() {
        return {
            userName: "张三",
            userLike: '篮球',
        }
    },
    //可通过$store.getters直接获取
    getters: {
        //state 局部状态
        changeName(state, getters, rootState) {
            console.log('user======getters========');
            console.log(getters);
            return state.userName = '李四';
        },
    },
    mutations: {
        //state表示上面state返回的对象 value表示传过来的参数
        changeLike(state) {
            state.userLike = '足球';
        }
    },
}
//其他 mutations和action等等差不多操作 详情可看官网
export default user

store index.js

//状态集中管理
//数据实现响应式
//使用场景: 权限管理 路径 对用户进行权限限制
import { createStore } from "vuex"
import user from "./user";
//创建store实例
const store = createStore({
  //存储的单一状态 存储基本数据
  state() {
    return {
      userAge: 16,
    }
  },
  getters: {
    changeAge(state,getters) {
      console.log('============getters===========');
      console.log(getters);
      return state.userAge = 19;
    }
  },
  modules:{
    user
  }
})
export default store

App.vue

<template>
  <h2>{{$store.state.userAge}}</h2>
  <h2>{{$store.getters.changeAge}}</h2>
  <br>
  <h2>{{$store.state.user.userName}}</h2>
  <br />
  <h2>{{$store.getters['user/changeName']}}</h2>
  <h2>{{$store.state.user.userLike}}</h2>
  <button @click="changeLike">改变喜好</button>
</template>
<script>
import { mapActions, mapGetters, mapMutations, mapState } from "vuex";

export default {
  computed: {
    //辅助函数 减少代码冗余
    ...mapGetters('user',['changeName'])
  },
  methods:{
    changeLike(){
     this.changeLike;
    },
    ...mapMutations('user',['changeLike'])
  }
};
</script>

运行结果

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

新生代农民工-小王八

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值