Vue-vuex

1、vuex

import { createStore } from "vuex"
import axios from 'axios'
import { INCREMENT_N } from './mutation-types'

const store = createStore({
  state() {
    return {
      counter: 100,
      name: "why",
      age: 18,
      height: 1.88,
      books: [
        { name: "深入Vuejs", price: 200, count: 3 },
        { name: "深入Webpack", price: 240, count: 5 },
        { name: "深入React", price: 130, count: 1 },
        { name: "深入Node", price: 220, count: 2 },
      ],
      discount: 0.6,
      banners: []
    };
  },
  getters: {
    totalPrice(state, getters) {
      let totalPrice = 0
      for (const book of state.books) {
        totalPrice += book.count * book.price
      }
      return totalPrice * getters.currentDiscount
    },
    currentDiscount(state) {
      return state.discount * 0.9
    },
    totalPriceCountGreaterN(state, getters) {
      return function(n) {
        let totalPrice = 0
        for (const book of state.books) {
          if (book.count > n) {
            totalPrice += book.count * book.price
          }
        }
        return totalPrice * getters.currentDiscount
      }
    },
    nameInfo(state) {
      return `name: ${state.name}`
    },
    ageInfo(state) {
      return `age: ${state.age}`
    },
    heightInfo(state) {
      return `height: ${state.height}`
    }
  },
  mutations: {
    increment(state) {
      state.counter++;
    },
    decrement(state) {
      state.counter--;
    },
    // 10 -> payload
    // {n: 10, name: "why", age: 18} -> payload
    [INCREMENT_N](state, payload) {
      console.log(payload);
      state.counter += payload.n
    },
    addBannerData(state, payload) {
      state.banners = payload
    }
  },
  actions: {
    // 放函数
    // 1.参数问题
    incrementAction(context, payload) {
      console.log(payload)
      setTimeout(() => {
        context.commit('increment')
      }, 1000);
    },
    // 2.context的其他属性
    decrementAction({ commit, dispatch, state, rootState, getters, rootGetters }) {
      commit("decrement")
    },
    getHomeMultidata(context) {
      return new Promise((resolve, reject) => {
        axios.get("http://123.207.32.32:8000/home/multidata").then(res => {
          context.commit("addBannerData", res.data.data.banner.list)
          resolve({name: "coderwhy", age: 18})
        }).catch(err => {
          reject(err)
        })
      })
    }
  }
});

export default store;

2、setup()中使用state 和 getters

// useState.js
import { mapState } from 'vuex'
import { useMapper } from './useMapper'

export function useState(mapper) {
    return useMapper(mapper, mapState)
}


// useGetters.js
import { mapGetters } from 'vuex'
import { useMapper } from './useMapper'

export function useGetters(mapper) {
    return useMapper(mapper, mapGetters)
}


// useMapper.js
import { computed } from 'vue'
import { matState, useStore } from 'vuex'

export function useMapper(mapper, mapFn) {
    // 拿到store 对象
    const store = useStore();
    
    // 获取到对应的对象的functions: { name: function, age: function }
    const storeStateFns = mapFn(mapper);
    
    // 对数据进行转换
    const storeState = {};
    Object.keys(storeStateFns).forEach(fnKey => {
        const fn = storeStateFns[fnKey].bind({ $store: store });
        storeState[fnKey] = computed(fn)
    })
    return storeState
}


// Home.vue
<template>
    <div>
        <h2>{{counter}} - {{name}}</h2>
        <h2>{{sCounter}} - {{sName}}</h2>
    </div>
</template>
<script>
    import { useState } from '../hooks/useState'
    export default {
        setup() {
            const storeState = useState(["counter", "name"]);
            const storeState2 = useState({
                sCounter: state => state.counter,
                sName: state => state.name
            })
            return {
                ...storeState,
                ...storeState2
            }
        }
    }
</script>

mutations

一、mutations 的使用

<template>
  <div>
    <h2>当前计数: {{ $store.state.counter }}</h2>
    <hr>
      <button @click="$store.commit('increment')">+1</button>
      <button @click="$store.commit('decrement')">-1</button>
      <button @click="addTen">+10</button>
    <hr>
  </div>
</template>

<script>
  import { INCREMENT_N } from '../store/mutation-types'

  export default {
    methods: {
      addTen() {
        // this.$store.commit('incrementN', 10)
        // this.$store.commit('incrementN', {n: 10, name: "why", age: 18})
        // 另外一种提交风格
        this.$store.commit({
          type: INCREMENT_N,
          n: 10, 
          name: "why", 
          age: 18
        })
      }
    }
  }
</script>

<style scoped>

</style>

 二、mutations 的辅助函数

<template>
  <div>
    <h2>当前计数: {{ $store.state.counter }}</h2>
    <hr>
      <button @click="increment">+1</button>
      <button @click="add">+1</button>
      <button @click="decrement">-1</button>
      <button @click="increment_n({n: 10})">+10</button>
    <hr>
  </div>
</template>

<script>
  import { mapMutations, mapState } from 'vuex'

  import { INCREMENT_N } from '../store/mutation-types'

  export default {
    methods: {
      ...mapMutations(["increment", "decrement", INCREMENT_N]),
      ...mapMutations({
        add: "increment"
      })
    },
    setup() {
      const storeMutations = mapMutations(["increment", "decrement", INCREMENT_N])

      return {
        ...storeMutations
      }
    }
  }
</script>

<style scoped>

</style>

3、Actions

一、actions 的使用

<template>
  <div>
    <h2>当前计数: {{ $store.state.counter }}</h2>
    <hr>
      <button @click="increment">+1</button>
      <button @click="decrement">-1</button>
    <hr>
  </div>
</template>

<script>
  import axios from 'axios'

  export default {
    methods: {
      increment() {
        this.$store.dispatch("incrementAction", {count: 100})
      },
      decrement() {
        // 3.派发风格(对象类型)
        this.$store.dispatch({
          type: "decrementAction"
        })
      }
    },
    mounted() {
      this.$store.dispatch("getHomeMultidata")
    },
    setup() {
    }
  }
</script>

<style scoped>

</style>

二、Actions 的辅助函数 mapActions

1、optionsApi

<template>
    <div>
        <button @click="incrementAction">+1</button>
        <button @click="decrementAction">-1</button>

        <button @click="add">+1</button>
        <button @click="sub">-1</button>
    </div>
</template>
<script>
    import { mapActions } from 'vuex'
    export default {    
        methods: {
            // 数组方式
            ...mapActions(["incrementAction", "decrementAction"]),
            // 对象方式
            ...mapActions({
                add: "incrementAction",
                sub: "decrementAction"
            })
            
        }
    }
</script>

2、compositionApi

<template>
    <div>
        <button @click="incrementAction">+1</button>
        <button @click="decrementAction">-1</button>

        <button @click="add">+1</button>
        <button @click="sub">-1</button>
    </div>
</template>
<script>
    import { mapActions } from 'vuex'
    export default {    
        setup() {
            const actions = mapActions(["incrementAction", "decrementAction"])
            const actions2 = mapActions({
                add: "incrementAction",
                sub: "decrementAction"
            })
            return {
                ...actions,
                ...actions2
            }
        }
        
    }
</script>

4、modules

一、modules 的使用

// store/index.js
import { createStore } from "vuex"
import home from './modules/home'
import user from './modules/user'

const store = createStore({
  state() {
    return {
      rootCounter: 100
    }
  },
  getters: {
    doubleRootCounter(state) {
      return state.rootCounter * 2
    }
  },
  mutations: {
    increment(state) {
      state.rootCounter++
    }
  },
  modules: {
    home,
    user
  }
});

export default store;



// store/home.js
const homeModule = {
  namespaced: true,
  state() {
    return {
      homeCounter: 100
    }
  },
  getters: {
    doubleHomeCounter(state, getters, rootState, rootGetters) {
      return state.homeCounter * 2
    },
    otherGetter(state) {
      return 100
    }
  },
  mutations: {
    increment(state) {
      state.homeCounter++
    }
  },
  actions: {
    incrementAction({commit, dispatch, state, rootState, getters, rootGetters}) {
      commit("increment")
      commit("increment", null, {root: true})

      // dispatch
      // dispatch("incrementAction", null, {root: true})
    }
  }
}
export default homeModule




// store/user.js
const userModule = {
  namespaced: true,
  state() {
    return {
      userCounter: 10
    }
  }
}
export default userModule




// pages/module的基本使用.js
<template>
  <div>
    <h2>{{ $store.state.rootCounter }}</h2>
    <h2>{{ $store.state.home.homeCounter }}</h2>
    <h2>{{ $store.state.user.userCounter }}</h2>
  </div>
</template>

二、modules 的命名空间

// store/index.js
import { createStore } from "vuex"
import home from './modules/home'
import user from './modules/user'

const store = createStore({
  state() {
    return {
      rootCounter: 100
    }
  },
  getters: {
    doubleRootCounter(state) {
      return state.rootCounter * 2
    }
  },
  mutations: {
    increment(state) {
      state.rootCounter++
    }
  },
  modules: {
    home,
    user
  }
});

export default store;



// store/home.js
const homeModule = {
  namespaced: true,
  state() {
    return {
      homeCounter: 100
    }
  },
  getters: {
    doubleHomeCounter(state, getters, rootState, rootGetters) {
      return state.homeCounter * 2
    },
    otherGetter(state) {
      return 100
    }
  },
  mutations: {
    increment(state) {
      state.homeCounter++
    }
  },
  actions: {
    incrementAction({commit, dispatch, state, rootState, getters, rootGetters}) {
      commit("increment")
      commit("increment", null, {root: true})

      // dispatch
      // dispatch("incrementAction", null, {root: true})
    }
  }
}
export default homeModule



// pages/modules 的命名空间.vue
<template>
  <div>
    <h2>root:{{ $store.state.rootCounter }}</h2>
    <h2>home:{{ $store.state.home.homeCounter }}</h2>
    <h2>user:{{ $store.state.user.userCounter }}</h2>

    <hr>
    <!-- <h2>{{ $store.getters.doubleHomeCounter }}</h2> -->
    <h2>{{ $store.getters["home/doubleHomeCounter"] }}</h2>

    <button @click="homeIncrement">home+1</button>
    <button @click="homeIncrementAction">home+1</button>
  </div>
</template>

<script>
  export default {
    methods: {
      homeIncrement() {
        this.$store.commit("home/increment")
      },
      homeIncrementAction() {
        this.$store.dispatch("home/incrementAction")
      }
    }
  }
</script>

三、modules 的辅助函数

<template>
  <div>
    <hr>
    <h2>{{ homeCounter }}</h2>
    <h2>{{ doubleHomeCounter }}</h2>
    <!-- <h2>{{ doubleRootCounter }}</h2> -->
    <button @click="increment">home+1</button>
    <button @click="incrementAction">home+1</button>
    <hr>
  </div>
</template>

<script>
  import { createNamespacedHelpers, mapState, mapGetters, mapMutations, mapActions } from "vuex";

  import { useState, useGetters } from '../hooks/index'

  // 写法三: 
  const { mapState, mapGetters, mapMutations, mapActions } = createNamespacedHelpers("home")

  export default {
    computed: {
      // 1.写法一:
      ...mapState({
        homeCounter: state => state.home.homeCounter
      }),
      ...mapGetters({
        doubleHomeCounter: "home/doubleHomeCounter"
      }),

      // 2.写法二:
      ...mapState("home", ["homeCounter"]),
      ...mapGetters("home", ["doubleHomeCounter"]),

      // 3.写法三:
      ...mapState(["homeCounter"]),
      ...mapGetters(["doubleHomeCounter"])
    },
    methods: {
      // 1.写法一:
      ...mapMutations({
        increment: "home/increment"
      }),
      ...mapActions({
        incrementAction: "home/incrementAction"
      }),

      // 2.写法二
      ...mapMutations("home", ["increment"]),
      ...mapActions("home", ["incrementAction"]),
      
      // 3.写法三:
      ...mapMutations(["increment"]),
      ...mapActions(["incrementAction"]),
    },

    setup() {
      // {homeCounter: function}
      const state = useState(["rootCounter"])
      const rootGetters = useGetters(["doubleRootCounter"])
      const getters = useGetters("home", ["doubleHomeCounter"])

      const mutations = mapMutations(["increment"])
      const actions = mapActions(["incrementAction"])

      return {
        ...state,
        ...getters,
        ...rootGetters,
        ...mutations,
        ...actions
      }
    }
  }
</script>


// hooks/useMappper.js
import { computed } from 'vue'
import { useStore } from 'vuex'

export function useMapper(mapper, mapFn) {
  // 拿到store独享
  const store = useStore()

  // 获取到对应的对象的functions: {name: function, age: function}
  const storeStateFns = mapFn(mapper)

  // 对数据进行转换
  const storeState = {}
  Object.keys(storeStateFns).forEach(fnKey => {
    const fn = storeStateFns[fnKey].bind({$store: store})
    storeState[fnKey] = computed(fn)
  })

  return storeState
}



// hooks/useState.js
import { mapState, createNamespacedHelpers } from 'vuex'
import { useMapper } from './useMapper'

export function useState(moduleName, mapper) {
  let mapperFn = mapState
  if (typeof moduleName === 'string' && moduleName.length > 0) {
    mapperFn = createNamespacedHelpers(moduleName).mapState
  } else {
    mapper = moduleName
  }

  return useMapper(mapper, mapperFn)
}



// hooks/useGetters.js
import { mapGetters, createNamespacedHelpers } from 'vuex'
import { useMapper } from './useMapper'

export function useGetters(moduleName, mapper) {
  let mapperFn = mapGetters
  if (typeof moduleName === 'string' && moduleName.length > 0) {
    mapperFn = createNamespacedHelpers(moduleName).mapGetters
  } else {
    mapper = moduleName
  }

  return useMapper(mapper, mapperFn)
}

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值