Vuex

src中文件

在App.vue中

<template>
  <div id='app'>
     这里是根组件
     <son1></son1>
     <son2></son2>
  </div>
</template>

<script>
import Son1 from './Son1.vue'
import Son2 from './Son2.vue'
export default {
  components: { Son1, Son2},//创建两个子组件在根组件中,并显示在跟组件
  methods: {
  }
}
</script>
<style>

</style>

在main.js里面

import Vue from 'vue'
import App from './App.vue' 
import store from './store/index' //导入'./store/index'的文件,并且在new vue实例的时候用
Vue.config.productionTip = false
new Vue({
  store,
  render: h => h(App),
}).$mount('#app')
 

在store下的index里面

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex);

const store = new Vuex.Store({
  state: {
    // 全局状态值
    name: '韩梅梅',
    age: 16,
    show: true,
  },
  getters: {
    hanlName(state) {
      return state.name + 'xxxxx' //在Son2中调用之后返回的是修改后的name
    }
  },
  mutations: {
    // vuex 规定想修改state必须通过mutations
    changName(state, params) {
     // state 全局状态
     console.log('mutation',state, params)/state里面是全局具有的参数,params是在son1里面commit里面传的第二个参数,也就是要改变的数据,注意是用来修改同步数据的,没法修改异步数据
     state.name = params
    },
    toggle(state,params) {
      console.log(params)
      state.show = !state.show
    }
  },
  actions: {
    changNameAction({ commit },params) {
      console.log('changNameAction')
      console.log(params)
      // 在action里通过commit 触发mution 来修改全局状态,是用来修改异步数据的
      
      setTimeout(()=>{
        commit('changName',params)//changName是mutations中的方法
      },1000)
    }
  }
})

export default store

在Son1中

<template>
  <div class='son1'>
    这里是组件1
    {{ this.$store.state.name }}//没有通过简单的方式渲染全局数据
    <button @click='change'>改名-commit</button>//点击改变同步数据,也就是全局有的
    <button @click='changeAction'>改名-action</button>//点击改变异步数据,就是全局需要异步加载的数据
    <button @click="mapchangeAction('🙂')">改名-mapaction</button>//通过插件,简单的方式进行修改名字
    <div v-if="this.$store.state.show" class='test'>//在SON2中通过点击改变全局的show来控制出现或者消失

    </div>
  </div>
</template>

<script>
import { mapActions } from 'vuex'
export default {
  name: 'son1',
  methods: {
    change() {
      this.$store.commit('changName','hehehda')//通过点击触发store下index里面的changName函数,把全局的name改成heheda,是同步
    },
    changeAction() {
      this.$store.dispatch('changNameAction','隔壁老王')//异步改变全局name
    },
    ...mapActions({ //简单的方法修改数据
      
      mapchangeAction: 'changNameAction'  //
    })
  },
  mounted() {
    console.log(this)
  }
}
</script>
<style>
.son1 {
  width: 300px;
  height: 300px;
  background: lightgreen;
}
.test{
  width: 50px;
  height: 50px;
  background: skyblue;
}
</style>

在son2中

<template>
  <div class='son2'>
    这里是组件2
     {{ this.$store.state.name }}
     {{ name }}
     <p>getters</p>
     {{ this.$store.getters.hanlName }}//渲染在store下的index的Getters下的hanlName 方法修改全局的name
     {{ hanlName }}
     <button @click="toggle">toggle</button>//点击控制SON1下test框的显示隐藏
     <button @click="toggleState(123)">mapMutation</button>//简单方式点击控制SON1下test框的显示隐藏
  </div>
</template>

<script>
import {mapState, mapGetters, mapMutations} from 'vuex'
/*
mapState 辅助函数 帮助我们简化state的使用过程
*/ 
export default {
  name: 'son1',
  computed:{ //这两个插件,为了在渲染页面的时候写的东西少,注意必须写在计算属性里面,渲染的时候直接{{name}}就行
    ...mapGetters({ hanlName:'hanlName'}),
    ...mapState({
      name: state => state.name,
      age: state => state.age,
      show: state => state.show
    }),
    test() {
      return false
    }
  },
  methods: {
    toggle() {
      // this.$store.commit('toggle')//点击后触发store下index里面的toggle,改变全局show去控制son1里面test的显示隐藏
      this.$store.commit({ type: 'toggle', name: 123})//可以传一个对象,//?参数传到哪里了
    },
    ...mapMutations({ toggleState: 'toggle'})
  },
  mounted() {
    console.log(this)
  }
}
</script>
<style>
.son2 {
  width: 300px;
  height: 300px;
  background: pink;
}
</style>

modules层

vue一共有 state ,mutations,actions,getters,modules 五层

通过购物车例子来讲解

下面是文件路径

首先在App.vue文件夹里面创建两个子组件,分别是Products,用来盛放商品列表的,另一个是shopcart用来存放购物车的列表,实现点击子组件Products里面的商品列表,就会渲染到shopCarts组件显示在根组件

在App.vue中,创建两个子组件,并且让子组件都显示在页面上

<template>
  <div id="app">
   <shop-cart></shop-cart>
   <hr>
   <products></products>
  </div>
</template>
<script>
import ShopCart from './components/ShopCart.vue'
import Products from './components/Products.vue'
export default {
  components:{
    ShopCart,Products
  }
}
</script>

 main.js里面

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

在store/index.js里面

import Vue from 'vue'
import Vuex from 'vuex'
import shopcart from './shopCart'//分别把两个字模块引入进来
import product from './Product'
Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    name:'韩梅梅'
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  },
  modules:{   //在modules里面进行引用
    shopcart,
    product
  },
})

store/product.js里面

export default {
    namespaced:true,//特定写法,允许使用模块化
    state:()=>({
        list:[] //首先创建一个list数组,用来当异步获取到数据后赋值给list,然后再通过list进行对Products组件进行渲染
    }),
    actions:{
        getProductList({commit},params){  //getProductList是Products组件里的一个方法,用来请求数据,在created的时候进行调用,但是函数体是store全局里面,因此映射过来,这里的prama是在Products组件里调用的时候传递的实参
            fetch('http://localhost:8082/project.json')
            .then(res=>res.json())
            .then((data) => {
              console.log(data)
              const { code, list } = data || {};
              if(code === 0) {   //再请求成功数据之后,就会调用mutations的setList函数,进行对当前product的全局下的list进行赋值操作,并把请求到的数据传递过去
                commit('setList', list)
              }
            })
        }
    },
    mutations:{
        setList(state,list){//state是当前全局状态下的数据
            state.list=list//对当前的list进行重新赋值
            // console.log(state.list);
            
        },
        decrementInventory(state, id){ //z这是为了点击让list中的inventory 进行减少,目的为了,前端的库存,例如目前库存就是10个,用户不能加到购物车11个,是通过点击的id进行对哪一个进行减少,当inventory 为0的时候就不在让点击
            const product = state.list.find(item => item.id === id);
            product.inventory --
          }
    }


}

component/Products组件

<template>
    <div>
        这里是商品列表  
        <ul>
      <li v-for='item in list' :key="item.id">{{item.title}} {{item.price}} {{item.inventory}}
      <button @click="addCartAction(item.id)" :disabled="!item.inventory">添加购物车</button></li></ul>//点击事件并把这个商品的id传递过去,知道点击的是哪个。  当list中某一个商品的数量为0的时候就不让加入到购物车,不让点击了
    </div>
</template>
<script>
import {mapState,mapActions,mapMutations} from 'vuex'//先引入映射的方法,写起来比较方便
export default {
    computed:{  //在全局里面的state数据写到computed计算属性里面
        ...mapState('product',['list']) //通过mapState方法获取到product模块的全局属性list,并且通过这个list渲染页面
    },
    methods:{
    ...mapActions('product',['getProductList']),//刚开始就获取数据的方法
    ...mapActions('shopcart',['addCartAction'])//点击添加到购物车组件的方法
    },
    mounted() {
    this.getProductList();//在created就进行异步获取数据

    console.log('商品列表',this)
  
  }
}
</script>

store/shopcar.js里面

export default{
    namespaced:true,//允许模块化
    state:()=>({
        carts:[]  首先创建一个数组,盛放在product组件里面点击的数据,当没有就push,有的话就数量++
    }), 
    getters:{
        allCarts(state, getters, rootState,rootGetters) { states是本模块的数据,getters是本模块的getter,rootStates是全部模块的数据,rootGetters是全部模块的getters

    //通过本模块的carts中数据的id对全部模块中product模块中的list进行筛选,并且把product模块中的list的数据进行给赋值,并返回,最后通过allCarts来进行渲染页面
            let result = state.carts.map(item => {
              const product = rootState.product.list.find((p) => p.id === item.id)
              return {
                id: item.id,
                title: product.title,
                price: product.price,
                count: item.count,
                sel: item.sel
              }
            })
            return result
          },
 totalCountAndPrice(state, getters, rootState,rootGetters) {
      let allCount = 0;
      let allPrice = 0;
      getters.allCarts.map(item => {//对当前模块里面的getters里的allCarts进行操作,因为allCarts是购物车里面的数据
        if(item.sel) { //如果选中的时候在进行操作,没选中就返回两个值都是0
          allCount += item.count
          allPrice += item.count * item.price
        }
        return item;
      })
      return {
        allCount,
        allPrice
      }
    },},
   actions:{
    addCartAction({commit},id){ product组件里面的点击事件,点击添加购物车,并把id带过来知道点击的是哪一个,是一个异步的事件,因为你点击之后并不知道就会添加成功,不能让他点击就会添加,而是进行判断,当添加成功后才会执行
        commit('addCarts',id) 
        commit('product/decrementInventory', id, { root: true })
    }
   },
   mutations:{  //执行添加事件,通过id进行过滤,添加到本模块的carts数组,没有就push,有的话count++
       addCarts(state,id){
        const existProduct = state.carts.find((product) => product.id === id)
           if(existProduct){
            existProduct.count++
           }else{
               state.carts.push({id,count:1,sel:true})
           }

       },
       selGoods(state, id) { //这里是shopcart组件里面多选框点击选中的还是不选中,改变cart里面的sel,在通过sel来控制:checked
        const existProduct = state.carts.find((product) => product.id === id)
        existProduct.sel = !existProduct.sel
      }
   }
}

component/shopcart.vue组件里面

<template>
  <div>
    这里是购物车
    <ul>
      <li v-for="item in allCarts" :key="item.id">//通过shopcart模块里的getter中的allCarts进行渲染页面
        <input type="checkbox" :checked="item.sel" @change="selGoods(item.id)">//点击按钮改变的时候触发selGoods函数,这个函数在shopcart模块里面,点击就会改变sel的值是false还是true,之后在通过这个来控制:checked是选中还是没选中
        {{item}} 
      </li>
    </ul>
    <hr>
    {{totalCountAndPrice.allCount}} | {{totalCountAndPrice.allPrice}}
    <!-- {{allCarts}} -->
    {{ totalCountAndPrice }}
  </div>
</template>
<script>
import { mapState, mapGetters, mapMutations } from 'vuex'//引入这三个书写简便的方法
export default {
  computed: {
  
    ...mapGetters('shopcart',['allCarts','totalCountAndPrice'])//映射过来shopcart模块的allCarts,与totalCountAndPrice来进行渲染页面
  },
  methods: {
    ...mapMutations('shopcart',['selGoods']) //是点击改变sel的方法,改变多选框的false还是true,是映射的shopcart模块里面的
  }
}
</script>

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值