“vue“: “^3.0.0“使用 “vuex“: “^4.1.0“

2 篇文章 0 订阅

1.安装

// 安装vuex
npm install vuex --save

2.创建store

import { createStore } from 'vuex'
const store = createStore({
    state:{
        counter:100,
        name:'zql',
        age: 45,
        height:180,
        book:[
            {name:'深入vue',price:200,count:30},
            {name:'深入react',price:150,count:20},
            {name:'深入webpack',price:100,count:60}
        ]
    },
    mutations: { // 方法 修改state唯一途径 同步操作
        increment(state) { // 默认就有个state参数,不用通过this.state
            state.counter++
        },
        decrement(state) {
            state.counter--
        }
    },
    actions: { // 如果有异步操作在这里写 比如网络请求
 
    },
    getters: {
 
    },
    modules: {
 
    }
})

export default store

3.挂载使用store --> main.js

import { createApp } from 'vue'
import App from './App.vue'
import store from './store'

createApp(App).use(store).mount('#app')

4.组件中使用store中的数据

第一种方法($store.state.xx和this.$store.commit('xx')):

<template>
    <div class="dome">
       <span>{{$store.state.counter}}</span>
       <button @click="increment">加1</button>
       <button  @click="decrement">减1</button>
    </div>
</template>

<script>
export default {
    data() {
    },
    created(){
    },
    methods:{
        increment(){
            this.$store.commit('increment')
        },
        decrement(){
            this.$store.commit('decrement')
        }
    }
}
</script>

<style scoped>
</style>

第二种方法 options API(3种)中 computed 和 映射mapState(1.数组写法,2.对象写法)

<template>
    <div class="dome">
       <span>{{sCounter}}</span>
       <button @click="increment">加1</button>
       <button  @click="decrement">减1</button>
        // <div>{{ sName }}</div>
        // <div>{{ sAge }}</div>
       <div>{{ name }}</div>
       <div>{{ age }}</div>
       <div>{{ height }}</div>
    </div>
</template>

<script>
import { mapState } from 'vuex'
export default {
    data() {
    },
    created(){
    },
    computed:{
       //第一种写法
        sCounter(){
            return this.$store.state.counter
        },

       //第二种写法
        ...mapState(['name','age','height'])//数组写法

       //第三种写法
       // ...mapState({ //对象写法
       //    sName: state => state.name,
       //    sAge: state => state.age
       // })
    },
    methods:{
        increment(){
            this.$store.commit('increment')
        },
        decrement(){
            this.$store.commit('decrement')
        }
    }
}
</script>

<style scoped>
</style>

第三种方法composition api (2种) setup()与mapState,computed

<template>
    <div class="dome">
       <span>{{sCounter}}</span>
       <button @click="increment">加1</button>
       <button @click="decrement">减1</button>
       {{ name }}
       {{ age }}
       {{ height }}
    </div>
</template>

<script>
import { mapState, useStore } from 'vuex'
import { computed } from 'vue'
export default {
    setup(){
        const store = useStore()
        // 第一种写法
        const sCounter = computed(()=> store.state.counter)

        // 第二种写法
        const storeStateFns = mapState(['name','age','height'])
        //{name:function,age:function,height:function}
        //{name:ref,age:ref,height:ref}
        const storeState ={}
        Object.keys(storeStateFns).forEach(fnkey =>{
            const fn = storeStateFns[fnkey].bind({$store:store});
            storeState[fnkey] = computed(fn)
        }) 
        return {
            sCounter,
            ...storeState
        }
    },
    methods:{
        increment(){
            this.$store.commit('increment')
        },
        decrement(){
            this.$store.commit('decrement')
        }
    }
}
</script>

<style scoped>
</style>
封装mapState与computed混用
import { mapState, useStore } from 'vuex'
import { computed } from 'vue'
function useState(item){
    // 拿到store对象
    const store = useStore()

    // 获取到对应的对象:{name:function,age:function,height:function}
    const storeStateFns = mapState(item)

    //对数据转化{name:ref,age:ref,height:ref}
    const storeState ={}
    Object.keys(storeStateFns).forEach(fnkey =>{
        const fn = storeStateFns[fnkey].bind({$store:store});
        storeState[fnkey] = computed(fn)
    })
    return storeState
}
export default useState

页面使用(数组,对象两种)

<template>
    <div class="dome">
       <span>{{counter}}</span>
       <button @click="increment">加1</button>
       <button @click="decrement">减1</button>
       {{ name }}
       {{ age }}
       {{ height }}
        {{ sCounter }}
        {{ sName }}
    </div>
</template>

<script>
import useState from './hook/useState'
export default {
    setup(){
        const storeState = useState(['counter','name','age','height'])//数组
        const storeState2 = useState({//对象
            sCounter: state=> state.counter,
            sName: state=> state.name,
        })
        return {
            ...storeState,
            ...storeState2
        }
    },
    methods:{
        increment(){
            this.$store.commit('increment')
        },
        decrement(){
            this.$store.commit('decrement')
        }
    }
}
</script>

<style scoped>
</style>

5.getters的创建以及使用

第一种基本使用

gatters ==》store

import { createStore } from 'vuex'
const store = createStore({
    state:{
        book:[
            {name:'深入vue',price:200,count:30},
            {name:'深入react',price:150,count:20},
            {name:'深入webpack',price:100,count:60}
        ]
    },
    mutations: { // 方法 修改state唯一途径 同步操作
    },
    actions: { // 如果有异步操作在这里写 比如网络请求
 
    },
    getters: {
        bookPrice(state){
            let bookPrice= 0
            for(const item of state.book){
                bookPrice += item.price * item.count
            }
            return bookPrice
        }
 
    },
    modules: {
    }
})

export default store

页面展示

<template>
    <div class="dome">
        书本总数{{$store.getters.bookPrice}}
    </div>
</template>
<script>
export default {
    setup(){
    },
    methods:{
    }
}
</script>

第二种使用其他getters

import { createStore } from 'vuex'
const store = createStore({
    state:{
        book:[
            {name:'深入vue',price:200,count:30},
            {name:'深入react',price:150,count:20},
            {name:'深入webpack',price:100,count:60}
        ],
        discount:0.6
    },
    mutations: { // 方法 修改state唯一途径 同步操作

    },
    actions: { // 如果有异步操作在这里写 比如网络请求
 
    },
    getters: {
        bookPrice(state, getters){
            let bookPrice= 0
            for(const item of state.book){
                bookPrice += item.price * item.count
            }
            return bookPrice * getters.bookDiscount
        },
        bookDiscount(state){
            return state.discount * 0.9
        }
    },
    modules: {
 
    }
})

export default store

<template>
    <div class="dome">
        书本总数{{$store.getters.bookPrice}}
    </div>
</template>
<script>
export default {
    setup(){
    },
    methods:{
    }
}
</script>

第三种返回函数

import { createStore } from 'vuex'
const store = createStore({
    state:{
        book:[
            {name:'深入vue',price:200,count:30},
            {name:'深入react',price:150,count:20},
            {name:'深入webpack',price:100,count:1}
        ],
        discount:0.6
    },
    mutations: { // 方法 修改state唯一途径 同步操作
    },
    actions: { // 如果有异步操作在这里写 比如网络请求
    },
    getters: {
        bookPrice(state, getters){
            let bookPrice= 0
            for(const item of state.book){
                bookPrice += item.price * item.count
            }
            return bookPrice * getters.bookDiscount
        },
        bookDiscount(state){
            return state.discount * 0.9
        },
        bookDiscountN(state, getters){
            return  function(N){
                let bookPrice= 0
                for(const item of state.book){
                    if(item.count > N){
                        bookPrice += item.price * item.count
                    }
                }
                return bookPrice * getters.bookDiscount
            }
        }
    },
    modules: {
 
    }
})

export default store

<template>
    <div class="dome">
        书本总数{{$store.getters.bookPrice}}
        筛选{{ $store.getters.bookDiscountN(6) }}
    </div>
</template>
<script>
export default {
    setup(){
    },
    methods:{
    }
}
</script>

第四种 options API(3种)中 computed 和 映射mapGetters(1.数组写法,2.对象写法)

import { createStore } from 'vuex'
const store = createStore({
    state:{
        counter:100,
        name:'zql',
        age: 45,
        height:180,
        book:[
            {name:'深入vue',price:200,count:30},
            {name:'深入react',price:150,count:20},
            {name:'深入webpack',price:100,count:1}
        ],
        discount:0.6
    },
    mutations: { // 方法 修改state唯一途径 同步操作
    },
    actions: { // 如果有异步操作在这里写 比如网络请求
    },
    getters: {
        nameInfo(state){
            return `name:${state.name}`
        },
        ageInfo(state){
            return `age:${state.age}`
        },
        heightInfo(state){
            return `height:${state.height}`
        },
        counterInfo(state){
            return `counter:${state.counter}`
        },
    },
    modules: {
 
    }
})

export default store

<template>
    <div class="dome">
        {{  $store.getters.nameInfo }}
        {{  ageInfo }}
        {{ heightInfo }}
        {{ counterInfo }}
    </div>
</template>

<script>
import { mapGetters } from 'vuex';
export default {
    computed:{
        // 第一种
        ageInfo(){
            return this.$store.getters.ageInfo
        },
        // 第二种数组
        ...mapGetters(['heightInfo']),
        // 第三种对象
        ...mapGetters({
            counterInfo:'counterInfo'
        })

    },
    setup(){

    },
    methods:{

    }
}
</script>

<style scoped>
</style>

第五种方法composition api (2种) setup()与mapGetters,computed

页面展示

<template>
    <div class="dome">
        {{  nameInfo }}
        {{  ageInfo }}
        {{  heightInfo }}
        {{  counterInfo }}

    </div>
</template>

<script>
import {computed} from 'vue'
import { useStore } from 'vuex'
import { mapGetters } from 'vuex';
import useMapper from './hook/useMapper'
export default {

    setup(){
        const store = useStore()
        const nameInfo = computed(()=>store.getters.nameInfo)//第一种

        const storeGettersFns = useMapper(['ageInfo','heightInfo','counterInfo'],mapGetters)//第二种函数封装
        return {
            nameInfo,
            ...storeGettersFns
        }
    },
    methods:{

    }
}
</script>

<style scoped>
</style>

封装

import { useStore } from 'vuex'
import { computed } from 'vue'
function useMapper(item,mapFn){
    // 拿到store对象
    const store = useStore()

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

    //对数据转化{name:ref,age:ref,height:ref}
    const storeState ={}
    Object.keys(storeStateFns).forEach(fnkey =>{
        const fn = storeStateFns[fnkey].bind({$store:store});
        storeState[fnkey] = computed(fn)
    })
    return storeState
}
export default useMapper

6.mutations的创建以及使用

mutations必须是同步函数,devtool会记录mutation的状态。

第一种基础写法(三种)

import { createStore } from 'vuex'
const store = createStore({
    state:{
        counter:100,
    },
    mutations: { // 方法 修改state唯一途径 同步操作
        increment(state) { // 默认就有个state参数,不用通过this.state
            state.counter++
        },
        decrement(state) {
            state.counter--
        },
        incrementN(state,payload) { // 默认就有个state参数,不用通过this.state
            state.counter += payload.n
        },
    },
    actions: { // 如果有异步操作在这里写 比如网络请求
    },
    getters: {
    },
    modules: {
    }
})

export default store

展示

<template>
    <div class="dome">
        {{  $store.state.counter }}

        <button @click="$store.commit('increment')">加1</button>
        //第一种

        <button @click="$store.commit('decrement')">减1</button>
        <button @click="addincrementN">加10</button>
    </div>
</template>

<script>
export default {
    methods:{
        addincrementN(){
            //第二种
            //this.$store.commit('incrementN',{n:10,name:'你好'})

            //第三种
            this.$store.commit({
                type:'incrementN',
                n:10,
                name:'你好'
            })
        }
    }
}
</script>
<style scoped>
</style>

第二种 options API辅助函数mapMutations

vuex使用上方

页面展示

<template>
    <div class="dome">

        {{  $store.state.counter }}
        <button @click="increment">加1</button>
        <button @click="decrement">减1</button>
        <button @click="incrementN({n:10})">加10</button>
    </div>
</template>

<script>
import { mapMutations } from 'vuex';
export default {
    methods:{
        //第一种数组
        ...mapMutations(['increment','decrement','incrementN'])

        //第二种对象
        //...mapMutations({
        //     add:'increment'
        // })
    }
}
</script>

<style scoped>
</style>

第三种方法composition api (1种) setup()与mapMutations

vuex使用上上方

<template>
    <div class="dome">
        {{  $store.state.counter }}
        <button @click="increment">加1</button>
        <button @click="decrement">减1</button>
        <button @click="incrementN({n:10})">加10</button>
    </div>
</template>

<script>
import { mapMutations } from 'vuex';
export default {

    setup(){
        const mutation = mapMutations(['increment','decrement','incrementN'])
        return {
            ...mutation
        }
    },
    methods:{
    }
}
</script>

<style scoped>
</style>

7.actions的使用

Action类似与mutation不用在于:

1.Action提交的是mutation,而不是直接修改状态,

2.Action可以包含任意异步操作。

Action还有一个context参数。context是一个和store实例均有相同方法和属性的context对象;

所以可以从其中获取到commit方法来提交一个mutation,或者通过context.state和context.getters来获取state和getters;

第一种基础写法(三种)

import { createStore } from 'vuex'
import axios from 'axios'

const store = createStore({
    state:{
        counter:100,
        banner:null
    },
    mutations: { // 方法 修改state唯一途径 同步操作
        increment(state) { // 默认就有个state参数,不用通过this.state
            state.counter++
        },
        decrement(state) {
            state.counter--
        },
    },
    actions: { // 如果有异步操作在这里写 比如网络请求
        incrementAction(context,number) {
            console.log('number',number)
            setTimeout(()=>{
                context.commit('increment')
            },1000)
        },
        decrementAction(context) {
            context.commit('decrement')
        },
        addBannerList(context){
            axios.get('http://123.207.32.32:8000/home/multidata').then((res)=>{
                // console.log(res.data.data.banner.list)
                context.commit('addBanner',res.data.data.banner.list)
            })
        }
    },
    getters: {
    },
    modules: {
    }
})

export default store

<template>
    <div class="dome">
        {{  $store.state.counter }}
        <button @click="add">加1</button>
        <button @click="decrement">减1</button>
    </div>
</template>

<script>
export default {

    mounted(){
        this.$store.dispatch('addBannerList')//第一种
    },
    methods:{
        add(){
            this.$store.dispatch('incrementAction',{count:'ll'})//第二种
        },
        decrement(){
            this.$store.dispatch({//第三种
                type:'decrementAction'
            })
        }
    }
}
</script>

<style scoped>
</style>

第二种 options API辅助函数mapActions

vuex上方雷同

页面展示

<template>
    <div class="dome">
        {{  $store.state.counter }}
        <button @click="incrementAction">加1</button>
        <button @click="decrementAction">减1</button>
    </div>
</template>

<script>
import { mapActions } from 'vuex';
export default {

    methods:{
       ...mapActions(['incrementAction','decrementAction']),//数组
       ...mapActions({ //对象
        add:'incrementAction',
        dec:'decrementAction'
       })
    }
}
</script>
<style scoped>
</style>

第三种方法composition api (2种) setup()与mapActions

vuex上上方雷同

页面展示

<template>
    <div class="dome">
        {{  $store.state.counter }}
        <button @click="incrementAction">加1</button>
        <button @click="decrementAction">减1</button>
    </div>
</template>

<script>
import { mapActions } from 'vuex';
export default {

    setup(){
      const action = mapActions(['incrementAction','decrementAction'])//数组
      const action2 = mapActions({//对象
            add:'incrementAction',
            dec:'decrementAction'
        })
      return{
        ...action,
        ...action2
      }
    },
}
</script>

<style scoped>
</style>

第四种 高级操作 知道action什么时候结束?通过Promise

import { createStore } from 'vuex'
import axios from 'axios'

const store = createStore({
    state:{
        banner:null
    },
    mutations: { 
        addBanner(state,payload) {
            state.banner = payload
        },
    },
    actions: { // 如果有异步操作在这里写 比如网络请求
        addBannerList(context){
            return new Promise((resove,rejack)=>{
                axios.get('http://123.207.32.32:8000/home/multidata').then((res)=>{
                    context.commit('addBanner',res.data.data.banner.list)
                    resove('成功')
                }).catch((err)=>{
                    rejack(err)
                })
            })
            
        }
    },
})
export default store

<template>
    <div class="dome">
    </div>
</template>

<script>
import { onMounted } from 'vue';
import {useStore} from'vuex'
export default {
    setup(){
        const store = useStore()
        onMounted(()=>{
            const actionPromise = store.dispatch('addBannerList')
            actionPromise.then((res)=>{
                console.log(res)
            }).catch((err)=>{
                console.log(err)
            })
        })
      return{
      }
    }
}
</script>

<style scoped>
</style>

8.moudle使用

基本使用

// homeModule.js
export default {
    namespaced: true,
    state() {
        return {
            title: "home"
        }
    },
}

// mineModuele.js
export default {
    namespaced: true,
    state() {
        return {
            title: "mine"
        }
    },
}

// rootModule.js
import { createStore } from 'vuex'
import home from './homeModule'
import mine  from './mineModule'

const store = createStore({
    state() {
        return {
            counter: 10,
            title: 'root'
        }
    },
    mutations: {
    },
    getters: {
    },
    actions: {
    },
    modules: {
        home,
        mine
    }
});

export default store;

// state数据的获取
<div>模板中获取值:{{$store.state.title}}</div>
<div>模板中获取值:{{$store.state.home.title}}</div>
<div>模板中获取值:{{$store.state.mine.title}}</div>
<div>模板中获取值:{{homeTitle}}</div>

computed: {
    homeTitle() {
        return this.$store.state.mine.title;
    }
}
        

多个module中使用getter和actions

homeModule.js
export default {
    namespaced: true,//命名空间,打开
    state() {
        return {
            title: "home"
        }
    },
    mutations: {
        changeTitle(state) {
            console.log(state);
        }
    },
    getters: {
        // getterTitle(state, getters, rootState, rootGetters)
        getterTitle(state) {
            return state.title + " getter"
        },
    },
    actions: {
        // context = {commit, dispatch, state, rootState, getters, rootGetters}
        changeTitleAction(context) {
            context.commit('changeTitle');
            // 派发root module中的mutations
            context.commit('changeTitle', null, {root: true});
        }
    }
}

// 模板
<button @click="changeTitle">changeTitle</button>
<div>{{$store.getters["home/getterTitle"]}}</div>

methods: {
    changeTitle() {
        this.$store.dispatch('home/changeTitleAction');
    }
}

在options API辅助函数中使用

<div>模板中获取值 - mapTitle:{{mapTitle}}</div>
<div>模板中获取值 - mapTitleHome: {{mapTitleHome}}</div>
<button @click="changeTitleAction">map changeTitle</button>
<button @click="homeObject">map homeObject</button>

import { mapState, mapActions,mapGetters,mapMutation } from "vuex";
export default {
    setup() {
        return {
        }
    },
    methods: {
        //写法一
        ...mapActions('home', ['changeTitleAction']),

        //写法二
        ...mapActions('home', {
            homeObject: 'changeTitleAction'
        })


        //写法一
        ...mapMutation("home", [incremet]),
        
         //写法二
        ...mapMutation('home',{
            incremet:"incremet"
        })
        },
    computed: {
        homeTitle() {
            return this.$store.state.mine.title;
        },
        //写法一
        ...mapState("home", [title]),
        //写法二
        ...mapState("home", {
            mapTitleHome: state => state.title
        }),
         //写法三
        ...mapState({
            mapTitle: state => state.home.title
        }),

        //写法一
        ...mapGetters("home", [doubleHimeCounter]),
        //写法二
        ...mapGetters('home',{
            doubleHimeCounter:"doubleHimeCounter"
        })

    }
}

利用options API createNamespacedHelpers导出使用

import { createNamespacedHelpers  } from "vuex";
const {mapState, mapActions,mapGetters,mapMutation} = createNamespacedHelpers("home");
export default {
    setup() {
        return {
        }
    },
    methods: {
        ...mapMutation([incremet]),

        ...mapActions(['changeTitleAction']),
        ...mapActions({
            homeObject: 'changeTitleAction'
        })
    },
    computed: {

        ...mapState([title]),

        ...mapState({
            mapTitle: state => state.title
        }),

         ...mapGetters([doubleHimeCounter]),
    }
}

composition api 封装

文件关系

index.js

import { useGetters } from './useGetters';
import { useState } from './useState';

export {
  useGetters,
  useState
}

useGetter.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)
}

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)
}

useMapper.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
}

页面使用

<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'

  export default {

    setup() {
      // {homeCounter: function}
      const state = useState("home",["rootCounter"])

     const getters = useGetters("home", ["doubleHomeCounter"])

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

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

<style scoped>

</style>
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值