vuex简述

本文详细介绍了Vuex在Vue应用中的核心概念,包括state、getter、mutation、action和模块的使用,以及组件间的通信和Vuex在多视图状态同步中的作用。同时涵盖了模块化结构和异步操作的处理。

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

1、概念:用户和视图交互更改状态的方式:actions,state:数据源,view:以声明方式将state映射到视图,数据的流向是单向的如下图:

2、组件间通信:a.父子组件通信:子组件给父组件传值:props/$emit---在父组件中可以通过@eventa="参数1+=$event"获取值也可以通过正常的函数形参获取值,

 b.其他组件间传值(自定义事件):常用eventBus其他$parent,$root,$children,$refs等,

3、vuex适用场景:a.多个视图以来同一状态,b.来自不同视图的行为需要变更同一状态

4、核心概念:store:容器,state:数据源(状态--响应式的),getter:内部对状态缓存只有数据改变时,才会重新计算,mutation:状态改变的提交,action:状态改变的提交(可以进行异步的操作),并最终还是提交到mutation,module:模块,如果数据过多可以分成多个module,每个module中有自己的state,getter,mutation,action以及潜逃的子模块

5、state的使用:a.在computed中使用

<div>
{{count}}
{{msg}}
</div>


<div>
{{num}}
{{message}}
</div>
import { mapState } from 'vuex'

export default{

    computed:{
        // count:state=>state.count

       ... mapState(['count','msg']) // count ,msg是在vuex中定义的数据
    /***
         将vuex中的count和msg赋给两个变量num和message

    **/
      ... mapState({ num:'count', message: 'msg'})  

    }

}

b.直接获取使用:

<div>
{{ $store.state.count }}
{{ $store.state.msg }}
</div>
import { mapState } from 'vuex'

export default{

   data(){
        return {
            count:this.$store.state.count
        }
    }
}

6、getter的使用(getter类似于computed):

/**vuex 的 index.js
**/

import Vue from 'vue'

import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.store({
   state:{
        count:0,
        msg:'Hello word'
    },
    getters:{
       reverseMsg(state){
           return state.msg.split('').reverse().join('')
        }
    }

})
<div>

  reveseMsg:{{$store.getters.reverseMsg}} // 对应mapState
  reveseMsg:{{reverseMsg}} // 对应mapGetters 
</div>

import { mapState,mapGetters } from 'vuex'

export default{

    computed:{
       ...mapGetters(['reverseMsg])

    }

}

7、Mutation(只支持同步的操作):有两种使用方式,方式一直接在标签中使用$store.commit('increase',2),方式二是通过引入mapMutation,并将相应的函数结构到methods中,这样在标签中可以直接使用该方法名进行触发例如...mapMutations([‘increase’]),是将mapMutations中increase函数结构到methods中这样在标签内可以如下调用<button @click="increase(2)">Mutation</button>;至于解构...mapMutations([‘increase’]),mutition也可以如getter那样以对象形式解构同样action也是如此

/**vuex 的 index.js
**/

import Vue from 'vue'

import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.store({
   state:{
        count:0,
        msg:'Hello word'
    },
    getters:{
       reverseMsg(state){
           return state.msg.split('').reverse().join('')
        }
    },
mutations:{

        increase(state,payload){
          state.count+=payload
        
        }

    }

})
<div>
/**方式一**/
<button @click="$store.commit('increase',2)">Mutation</button>
/**方式二**/
<button @click="increase(2)">Mutation</button>
</div>

import { mapState,mapGetters,mapMutations } from 'vuex' //方式二将mapMutations放到methods中

export default{

    computed:{
       ...mapGetters(['reverseMsg])

    },
    methods:{
        ...mapMutations([‘increase’])  //方式二将mapMutations放到methods中

    }

}

8、Action(异步操作),当操作完成后需要提交变更状态的时候需要提交Mutation来修改state:action的调用需要通过dispatch

/**vuex 的 index.js
**/

import Vue from 'vue'

import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.store({
   state:{
        count:0,
        msg:'Hello word'
    },
    getters:{
       reverseMsg(state){
           return state.msg.split('').reverse().join('')
        }
    },
    mutations:{

        increase(state,payload){
          state.count+=payload
        
        }

    },
    action:{

        increaseAsync(context,payload){
             setTimeout(()=>{
                
            context.commit('increase',payload)
            },2000)
        }

    }

})
<div>
/**方式一**/
<button @click="$store.dsspatch('increaseAsync',2)">Action</button>
/**方式二**/
<button @click="increaseAsync(2)">Mutation</button>
</div>

import { mapState,mapGetters,mapActions} from 'Action' //方式二将mapActions放到methods中

export default{

    computed:{
       ...mapGetters(['reverseMsg])

    },
    methods:{
        ...mapActions([‘increaseAsync’])  //方式二将mapMutations放到methods中

    }

}

9、module:目录结构如下:

/***
   cart.js

***/
const state = {
  cartProducts: JSON.parse(window.localStorage.getItem('cart-products')) || []
}
const getters = {
  totalCount (state) {
    return state.cartProducts.reduce((sum, prod) => sum + prod.count, 0)
  },
  totalPrice (state) {
    return state.cartProducts.reduce((sum, prod) => sum + prod.totalPrice, 0)
  },
  checkedCount (state) {
    return state.cartProducts.reduce((sum, prod) => {
      if (prod.isChecked) {
        sum += prod.count
      }
      return sum
    }, 0)
  },
  checkedPrice (state) {
    return state.cartProducts.reduce((sum, prod) => {
      if (prod.isChecked) {
        sum += prod.totalPrice
      }
      return sum
    }, 0)
  }
}
const mutations = {
  addToCart (state, product) {
    // 1. cartProducts 中没有该商品,把该商品添加到数组,并增加 count,isChecked,totalPrice
    // 2. cartProducts 有该商品,让商品的数量加1,选中,计算小计
    const prod = state.cartProducts.find(item => item.id === product.id)
    if (prod) {
      prod.count++
      prod.isChecked = true
      prod.totalPrice = prod.count * prod.price
    } else {
      state.cartProducts.push({
        ...product,
        count: 1,
        isChecked: true,
        totalPrice: product.price
      })
    }
  },
  deleteFromCart (state, prodId) {
    const index = state.cartProducts.findIndex(item => item.id === prodId)
    index !== -1 && state.cartProducts.splice(index, 1)
  },
  updateAllProductChecked (state, checked) {
    state.cartProducts.forEach(prod => {
      prod.isChecked = checked
    })
  },
  updateProductChecked (state, {
    checked,
    prodId
  }) {
    const prod = state.cartProducts.find(prod => prod.id === prodId)
    prod && (prod.isChecked = checked)
  },
  updateProduct (state, {
    prodId,
    count
  }) {
    const prod = state.cartProducts.find(prod => prod.id === prodId)
    if (prod) {
      prod.count = count
      prod.totalPrice = count * prod.price
    }
  }
}
const actions = {}

export default {
  namespaced: true,//开启命名空间可以在使用的时候更加方便的使用解构
  state,
  getters,
  mutations,
  actions
}
/***
 product.js

***/

import axios from 'axios'
const state = {
  products: []
}
const getters = {}
const mutations = {
  setProducts (state, payload) {
    state.products = payload
  }
}
const actions = {
  async getProducts ({ commit }) {
    const { data } = await axios({
      method: 'GET',
      url: 'http://127.0.0.1:3000/products'
    })
    commit('setProducts', data)
  }
}

export default {
  namespaced: true, //开启命名空间可以在使用的时候更加方便的使用解构
  state,
  getters,
  mutations,
  actions
}
/***
vuex的index.js


****/

import Vue from 'vue'
import Vuex from 'vuex'
import products from './modules/products'
import cart from './modules/cart'

Vue.use(Vuex)

const myPlugin = store => {
  store.subscribe((mutation, state) => {
    if (mutation.type.startsWith('cart/')) {
      window.localStorage.setItem('cart-products', JSON.stringify(state.cart.cartProducts))
    }
  })
}

export default new Vuex.Store({
  state: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
    products,
    cart
  },
  plugins: [myPlugin]
})

使用:

  <h2>Module</h2>

/***
    第一个products是模块的名字,第二个products是模块中state的属性

***/

// 方式一
    products: {{ $store.state.products.products }} <br> 
   <button @click="$store.commit('setProducts', [])">Mutation</button> 

// 方式二

 products: {{ products }} <br> 
   <button @click="setProducts([])">Mutation</button> 




 computed: {
    ...mapState('products', ['products'])
  },
  methods: {
    ...mapMutations('products', ['setProducts'])
  }

 10.vuex插件:vuex插件是一个函数,其接收一个store的参数,插件:例如

/***
 插件定义

***/
const myPlugin = store => {

  //当store初始化后调用

  store.subscribe((mutation, state) => {

   /***每次mutation之后调用,mutation的格式为:{type,payload},subscribe 订阅vuex的某个动作这里            
      订阅的是mutation***/

    if (mutation.type.startsWith('cart/')) { // mutation.type=命名空间+mutation的名字
      window.localStorage.setItem('cart-products', JSON.stringify(state.cart.cartProducts))
    }
  })
}

插件的注册:

// 插件注册
export default new Vuex.Store({
   // ...
  plugins: [myPlugin]
})

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值