Vuex是什么

Vuex是一个专为Vue.js应用程序开发的状态管理模式,它提供了集中式的存储,确保状态以可预测的方式变化。状态存储是响应式的,状态的改变只能通过提交mutation进行,这便于跟踪状态变化。组件通过计算属性和getter访问状态,而action则用于处理异步操作并触发mutations。此外,Vuex支持模块化,帮助管理大型应用的状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

vuex

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

1.store

每一个Vuex应用的核心就是store(仓库),store基本上就是一个容器,包含着你的应用中大部分的状态(state)。vuex和单纯的全局对象有2点不同:

1.vuex的状态存储是响应式的。当vue组件从store中读取状态时候,若store中的状态发生变化,相应的组件也会相应的得到更新。

2.你不能直接改变store中的状态。改变store中的唯一途径就是显示的提交(commit)mutation。这样使得我们方便的追踪每一个状态的变化。

创建一个store
<html>
    <head>
        </head>                                      
        <body>                                     
               <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>  
               <script src="https://unpkg.com/vuex@4.0.0/dist/vuex.global.js"></script>
         <div >
       
         </div>                                                           
<script>                                                                                                    
 const { createApp } = Vue
const { createStore } = Vuex
// 创建一个新的 store 实例
const store = createStore({
  state () {
    return {
      count: 0
    }
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
})


const Counter={
template:`<div>{{count}}</div>`,
computed:{
     count(){
          return store.state.count;
     }
}
};
const app = createApp({ /* 根组件 */ });

// 将 store 实例作为插件安装
app.use(store);   
store.commit('increment');
console.log(store.state.count); 

</script> 
            </body>
    </html>

可以通过store.state来获取状态对象,通过store.commit来触发状态变更:

store.commit("increment");
console.log(store.state.count);

在Vue组件中,可以通过this.$store访问store实例,现在我们可以从组件的方法提交一个变更。

<html>
    <head>
        </head>                                                                                                                             
        <body>                                                                                                  
              
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>  
               <script src="https://unpkg.com/vuex@4.0.0/dist/vuex.global.js"></script>
         <div id="app">
     
       <button @click="itn">+</button>
         </div>                                                           
<script>                                                                                                    
 const { createApp } = Vue
const { createStore } = Vuex
// 创建一个新的 store 实例
const store = createStore({
  state () {
    return {
      count: 0
    }
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
})

const app = createApp({ /* 根组件 */ 

  methods:{
     itn(){
          this.$store.commit('increment')
          console.log(this.$store.state.count);
     }
}
})

// 将 store 实例作为插件安装
app.use(store);   
app.mount("#app");

</script> 

            </body>
    </html>

再次强调,我们通过提交mutation的方式,而非直接改变store.state.count,是因为我们想要更明确的追踪到状态的变化。

由于store的状态是响应式的,在组件中调用store中的状态简单到仅需在计算属性中返回即可,触发变化也仅仅是在组件的methods中提交mutation

2.State

在vue组件中获得Vuex状态

由于Vuex的状态存储是响应式的,从store实例中读取状态最简单的方法:为在计算属性中返回某个状态:

const counter={
     template:`<div>{{count}}</div>`,
     computed:{
          count(){
               return store.state.count;
          }
     }
};

完整代码:

<html>
    <head>
        </head>                                                                                                                             
        <body>                                                                                                  
              
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>  
               <script src="https://unpkg.com/vuex@4.0.0/dist/vuex.global.js"></script>
         <div id="app">
      <my-component></my-component>
       <button @click="itn">+</button>
         </div>                                                           
<script>                                                                                                    
 const { createApp } = Vue
const { createStore } = Vuex
// 创建一个新的 store 实例
const store = createStore({
  state () {
    return {
      count: 0
    }
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
})


const counter={
     template:`<div>{{count}}</div>`,
     computed:{
          count(){
               return store.state.count;
          }
     }
};




const app = createApp({ /* 根组件 */ 
  methods:{
     itn(){
          this.$store.commit('increment')
          console.log(this.$store.state.count);
     }
},
components:{
     "my-component":counter
}
})

// 将 store 实例作为插件安装
app.use(store);   
app.mount("#app");

</script> 

            </body>
    </html>

每当store.state.count变化的时候,都会重新求取计算属性,并且触发更多相关联的dom。

然而,这种模式导致组件依赖全局状态单例。在模块化的构建系统中,在每个需要使用state的组件中频繁的导入,并在测试组件时需要模拟状态。

vuex通过vue的插件系统将store实例从根组件注入到所有的子组件中。且子组件通过this.store访问到,

const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return this.$store.state.count
    }
  }
}

3.Getter

有时我们从store中的state中派生出一些状态。

如果有多个组件需要用到此属性,我们要么复制这个函数,或者抽取到一个共享函数然后在多处导入它。

Vuex允许我们在store中定义getter,getter类似于计算属性值。

在getters中定义了doneTodos函数,该方法接收state参数,filter方法接收的参数为箭头函数,箭头函数的参数todo表示数组中的每一个对象,使用todo.done作为返回值返回,若返回值为true,在filter方法返回的数组中添加todo。

<html>
    <head>
        </head>                                                                                                                             
        <body>                                                                                                  
              
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>  
               <script src="https://unpkg.com/vuex@4.0.0/dist/vuex.global.js"></script>
         <div id="app">
<p>{{this.$store.getters}}</p>
         </div>                                                           
<script>                                                                                                    
 const { createApp } = Vue
const { createStore } = Vuex
// 创建一个新的 store 实例
const store=createStore({
     state:{
          todos:[
               {id:1,text:"success",done:true},
               {id:2,text:"failure",done:false}
          ]
     },
     getters:{
          doneTodos(state){
               return state.todos.filter(todo=>todo.done);
          }

     }

})







const app = createApp({ /* 根组件 */ 

})

// 将 store 实例作为插件安装
app.use(store);   
app.mount("#app");

</script> 

            </body>
    </html>

结果表示捕获到了todos数组中done为true的值
在这里插入图片描述

利用getters还可以获取doneTodos的数组,以及length值,getter也可以接收其他getter作为第二个参数值

getters:{
  doneTodosCount:(state,getters)=>{
    return getters.doneTodos.length;
  }
}

完整代码:

<html>
    <head>
        </head>                                                                                                                             
        <body>                                                                                                  
              
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>  
               <script src="https://unpkg.com/vuex@4.0.0/dist/vuex.global.js"></script>
         <div id="app">
<p>{{this.$store.getters.doneTodosCount}}</p>
         </div>                                                           
<script>                                                                                                    
 const { createApp } = Vue
const { createStore } = Vuex
// 创建一个新的 store 实例
const store=createStore({
     state:{
          todos:[
               {id:1,text:"success",done:true},
               {id:2,text:"failure",done:false}
          ]
     },
     getters:{
          doneTodos(state){
               return state.todos.filter(todo=>todo.done);
          },

  doneTodosCount:(state,getters)=>{
    return getters.doneTodos.length;
  }
}


})






const app = createApp({ /* 根组件 */ 

})

// 将 store 实例作为插件安装
app.use(store);   
app.mount("#app");

</script> 

            </body>
    </html>

结果:
在这里插入图片描述
注意,getter 在通过属性访问时是作为 Vue 的响应式系统的一部分缓存其中的。

4.Mutation

更改Vuex的store的状态的唯一方法为提交mutation。Vuex中的mutation非常类似于事件:每个mutation有一个回调函数,这个回调函数是我们进行状态更改,他会接收state作为第一个参数:

const store = createStore({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // 变更状态
      state.count++
    }
  }
})

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

store.commit("increment")

完整代码:

<html>
    <head>
        </head>                                                                                                                             
        <body>                                                                                                  
              
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>  
               <script src="https://unpkg.com/vuex@4.0.0/dist/vuex.global.js"></script>
         <div id="app">
<p>{{this.$store.state.count}}</p>
         </div>                                                           
<script>                                                                                                    
 const { createApp } = Vue
const { createStore } = Vuex
// 创建一个新的 store 实例
const store=createStore({
     state:{
          count:1
     },
   mutations:{
        increment(state){
             state.count++;
        }
   }
})

const app = createApp({ /* 根组件 */ 
  
})

// 将 store 实例作为插件安装
app.use(store);   
app.mount("#app");
store.commit("increment");

</script> 

            </body>
    </html>

显示结果为2

提交载荷(Payload)

可以向store.commit传入额外的参数,即mutation的载荷(payload):

<html>
    <head>
        </head>                                                                                                                             
        <body>                                                                                                  
              
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>  
               <script src="https://unpkg.com/vuex@4.0.0/dist/vuex.global.js"></script>
         <div id="app">
<p>{{this.$store.state.count}}</p>
         </div>                                                           
<script>                                                                       
 const { createApp } = Vue
const { createStore } = Vuex
// 创建一个新的 store 实例
const store=createStore({
     state:{
          count:1
     },
   mutations:{
        increment(state,n){
             state.count+=n;
        }
   }
})


const app = createApp({ /* 根组件 */ 
})

// 将 store 实例作为插件安装
app.use(store);   
app.mount("#app");
store.commit("increment",10);

</script> 

            </body>
    </html>

结果为11

在大多数情况下,载荷应该是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读:

<html>
    <head>
        </head>                                                                                                                             
        <body>                                                                                                  
              
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>  
               <script src="https://unpkg.com/vuex@4.0.0/dist/vuex.global.js"></script>
         <div id="app">
<p>{{this.$store.state.count}}</p>
         </div>                                                           
<script>                                                                                                    
 const { createApp } = Vue
const { createStore } = Vuex
// 创建一个新的 store 实例
const store=createStore({
     state:{
          count:1
     },
   mutations:{
        increment(state,payload){
             state.count+=payload.amount;
        }
   }
})


const app = createApp({ /* 根组件 */ 
  
})

// 将 store 实例作为插件安装
app.use(store);   
app.mount("#app");
store.commit("increment",{
     amount:10
});

</script> 

            </body>
    </html>
对象风格提交方式

提交mutation的另一种方式为直接使用包含type属性的对象,当使用对象风格的提交方式,整个对象都作为载荷传给mutation函数,因此处理函数保持不变:

<html>
    <head>
        </head>                                                                                                                             
        <body>                                                                                                  
              
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>  
               <script src="https://unpkg.com/vuex@4.0.0/dist/vuex.global.js"></script>
         <div id="app">
<p>{{this.$store.state.count}}</p>
         </div>                                                           
<script>                                                                                                    
 const { createApp } = Vue
const { createStore } = Vuex
// 创建一个新的 store 实例
const store=createStore({
     state:{
          count:1
     },
   mutations:{
        increment(state,payload){
             state.count+=payload.amount;
        }
   }
})


const app = createApp({ /* 根组件 */ 
  
})

// 将 store 实例作为插件安装
app.use(store);   
app.mount("#app");
store.commit({type:"increment",amount:10});

</script> 

            </body>
    </html>
同步函数

mutations是同步函数,组件状态发生变化时,触发mutations中的事件处理方法来更新页面状态的变化,这是一种同步状态。同步方法是同步执行的,主要可以记录当前状态的变化,同步到页面。

5.Action

Action类似于mutation,不同在于:
1.Action提交的是mutation,而不是直接变更状态
2.Action可以包含任意操作

actions用来定义事件处理方法,用于处理state数据,actions是异步执行的,事件处理函数可以接受{commit}对象,完成mutation提交

首先先注册一个简单的action:

const store=createStore({
     state:{
          count:1
     },
   mutations:{
        increment(state,payload){
             state.count+=payload.amount;
        }
   },
   actions:{
        increment(context){
             context.commit("increment");
        }
   }
})

Actions接收一个与store实例具有相同方法和属性的context对象,因此可以调用context.commit提交一个mutation,或者通过context.state和context.getters来获取state和getters和dispath。

actions: {
  increment ({ commit }) {
    commit('increment')
  }
}
分发action

Action通过store.dispath方法触发:

store.dispatch("increment");

完整代码:

<html>
    <head>
        </head>                                                                                                                             
        <body>                                                                                                  
              
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>  
               <script src="https://unpkg.com/vuex@4.0.0/dist/vuex.global.js"></script>
         <div id="app">
              <button @click="calc">+</button>
<p>{{this.$store.state.count}}</p>
         </div>                                                           
<script>                                                                                                    
 const { createApp } = Vue
const { createStore } = Vuex
// 创建一个新的 store 实例
const store=createStore({
     state:{
          count:1
     },
   mutations:{
        increment(state){
             state.count++;
        }
   },
   actions:{
     add(context){            //在store实例的actions中定义了add方法,add方法接收参数context参数
             context.commit("increment");   //使用commit推送一个名称为increment的mutation,对应mutations中的increment方法
        }
   }
})


const app = createApp({ /* 根组件 */ 
  methods:{
       calc(){
            this.$store.dispatch("add");    //通过dispatch来推送一个名称为add的action
       }
  }
})

// 将 store 实例作为插件安装
app.use(store);   
app.mount("#app");


</script> 
            </body>
    </html>
6.module

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

Vuex允许我们将store分割为模块(module)。每个模块拥有自己的state、mutation、action、getter

<html>
    <head>
        </head>                                                                                                                             
        <body>                                                                                                  
              
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>  
               <script src="https://unpkg.com/vuex@4.0.0/dist/vuex.global.js"></script>
         <div id="app">
              <button @click="calc">+</button>
<p>{{this.$store.state.count}}</p>
         </div>                                                           
<script>                                                                                                    
 const { createApp } = Vue
const { createStore } = Vuex


const moduleA={
     state:{
          nameA:"A"
     }
}

const moduleB={
     state:{
          nameB:"B"
     }
}

// 创建一个新的 store 实例
const store=new Vuex.Store({
     modules:{
          a:moduleA,
          b:moduleB
     }
})





const app = createApp({ /* 根组件 */ 
  
})

// 将 store 实例作为插件安装
app.use(store);   
app.mount("#app");


console.log(store.state.a);
console.log(store.state.b);

</script> 

            </body>
    </html>

在这里插入图片描述

Vuex是一个状态管理模式,在Vue.js应用程序中使用。它可以集中管理Vue应用程序中的所有组件的状态,使得状态的共享和修改变得更加容易和可控。 Vuex有五个核心概念:state、getter、mutation、action和module。 - state:用于存储状态数据的对象。 - getter:类似于Vue组件中的计算属性,用于在状态发生变化时派生出新的状态。 - mutation:用于修改状态的方法,必须是同步的。 - action:用于提交mutation,可以是异步的。 - module:用于将状态分割成更小的模块,每个模块都拥有自己的state、getter、mutation和action。 使用Vuex的步骤如下: 1. 安装Vuex:在Vue.js项目中运行npm install vuex。 2. 创建store:在Vue.js项目中创建一个store.js文件,用于创建Vuex的store对象。 3. 定义state:在store.js文件中定义state对象,用于存储状态数据。 4. 定义mutation:在store.js文件中定义mutation方法,用于修改state中的数据。 5. 定义getter:在store.js文件中定义getter方法,用于派生出新的状态数据。 6. 定义action:在store.js文件中定义action方法,用于提交mutation。 7. 将store注入到Vue应用程序中:在Vue.js项目中的main.js文件中导入store并将其注入到Vue实例中。 8. 在组件中使用Vuex:在Vue.js组件中使用Vuex的state、getter、mutation和action方法。可以通过this.$store来访问store中的数据和方法。 示例代码: // store.js import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment(state) { state.count++ } }, getters: { doubleCount(state) { return state.count * 2 } }, actions: { incrementAsync({commit}) { setTimeout(() => { commit('increment') }, 1000) } } }) export default store // main.js import Vue from 'vue' import App from './App.vue' import store from './store' new Vue({ store, render: h => h(App) }).$mount('#app') // App.vue <template> <div> <p>Count: {{ count }}</p> <p>Double Count: {{ doubleCount }}</p> <button @click="increment">Increment</button> <button @click="incrementAsync">Increment Async</button> </div> </template> <script> export default { computed: { count() { return this.$store.state.count }, doubleCount() { return this.$store.getters.doubleCount } }, methods: { increment() { this.$store.commit('increment') }, incrementAsync() { this.$store.dispatch('incrementAsync') } } } </script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值