Vuex是什么

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>

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值