09 Vue3 vuex数据共享&持久化&TS

一、Vuex

Vues是一个转为Vue.js应用程序开发的状态管理模式

官网:https://next.vuex.vuejs.org/zh/

主要功能:

1、Vuex可以实现vue不同组件之间的状态共享(解决了不同组件之间的数据共享)

2、可以实现组件里面数据的持久化

1.0 Vuex的几个核心概念

  • State : 定义数据
  • Getters : 计算属性
  • Mutations : 定义方法
  • Actions : 异步
  • Modules :合并多个创建的store

1.1 安装

npm install vuex@next --save

yard add vuex@next --save

1.2 State Mutations

使用步骤
  1. 在src下创建vuex文件夹,并在里面创建store.js文件

  2. 在main.ts 里进行挂载

  3. 在各组件里面进行调用

创建store.js
import {createStore} from 'vuex';
const store = createStore({
    // 定义数据 调用数据:this.$store.state.count;  标签里直接使用$store.state.count
    state() {
        return {
            count: 1
        }
    },
    // 定义方法 调用方法:this.$store.commit("incCount")
    mutations: {
        incCount(state) {
            // 使state里的数据count++
            state.count++
        },
        // 接收参数
        setCount(state, num) {
            state.count = num
        }
    }
});

export default store;
main.ts挂载
import {createApp} from 'vue'
import App from './App.vue'
// 引入配置好的路由
import router from "@/routes";
import store from "./vuex/store.js"

// 老写法
// createApp(App).mount('#app');

const app = createApp(App);
// 挂载路由
app.use(router);
// 挂载vuex
app.use(store);
app.mount('#app');
组件里使用
<template>
    <h1>Home组件 --{{num}} --- {{$store.state.count}}</h1>
    <button @click="incCount">执行vuex里的方法incCount</button>
    <br>
    <button @click="setCount">执行vuex里的方法setCount,并进行传值</button>
</template>

<script>
    import {defineComponent} from 'vue';

    export default defineComponent({
        name: "Home",

        methods: {
            incCount() {
                // 调store里的incCount方法
                this.$store.commit("incCount")
            },
            setCount() {
                // 调store里的setCount方法,并进行传参
                this.$store.commit("setCount", 20);
            }
        },
        computed: {
            num() {
                // 获取store里的stage的count值
                return this.$store.state.count;
            }
        }
    })
</script>

<style lang="scss" scoped>

</style>

1.3 使用mapState

映射state里的数据,方便组件使用

store.js
import {createStore} from 'vuex';
const store = createStore({
    // 定义数据
    state() {
        return {
            count: 1,
            list: ["马总", "刘总", "李总"]
        }
    },
});
export default store;
组件中使用
<template>
    <ul>
        <!--此时这里可以使用mapState映射好的数据-->
        <li v-for="(item, index) in list" :key="index">{{item}}</li>
    </ul>
</template>

<script>
    import {defineComponent} from 'vue';
    import {mapState} from 'vuex'

    export default defineComponent({
        name: "Home",
        computed: {
            num() {
                // 获取store里的stage的count值
                return this.$store.state.count;
            },
            // 第一种方法(更直接,注意,名字和stage里的名字要保持一直)
            // ...mapState([
            //     "count",
            //     "list"
            // ])
            // 第二种方法,起别名
            ...mapState({
                count: (state) => state.count,
                list: (state) => state.list,
            })
        }
    })
</script>

<style lang="scss" scoped>

</style>

1.4 Getters

store.js
import {createStore} from 'vuex';


const store = createStore({
    // 定义数据 调用数据:this.$store.state.count;
    state() {
        return {
            count: 1,
            msg: "你好Vue"
        }
    },
    // 类似于computed属性,计算属性 调用:this.$store.getters.reverseMsg
    getters: {
        reverseMsg(state) {
            return state.msg.split("").reverse().join("")
        },
        num(state) {
            return state.count + 10;
        }
    }
});

export default store;
组件中使用
<template>
    <h1>User组件</h1>
    {{reverseMsg}} <br>
    {{num}}
</template>

<script>
    import {defineComponent} from 'vue';

    export default defineComponent({
        name: "User",
        computed: {
            reverseMsg() {
                // 调用vuex里的getters
                return this.$store.getters.reverseMsg
            },
            num(){
                return this.$store.getters.num
            }
        }
    })
</script>

<style lang="scss" scoped>
</style>

1.5 使用mapGetters

组件中使用
<template>
    <h1>User组件</h1>
    {{reverseMsg}} <br>
    {{num}}
</template>

<script>
    import {defineComponent} from 'vue';
    import {mapGetters} from 'vuex';

    export default defineComponent({
        name: "User",
        computed: {
            // 第一种方法
            // ...mapGetters([
            //     "reverseMsg",
            //     "num"
            // ])

            // 第二种方法
            ...mapGetters({
                reverseMsg: "reverseMsg",
                num: "num"
            })
        }
    })
</script>

<style lang="scss" scoped>
</style>

1.6 Actions

store.js
import {createStore} from 'vuex';


const store = createStore({
    // 定义数据 调用数据:this.$store.state.count;
    state() {
        return {
            count: 1,
            list: ["马总", "刘总", "李总"],
            msg: "你好Vue"
        }
    },
    // 定义方法 调用方法:this.$store.commit("incCount")
    mutations: {
        incCount(state) {
            // 使state里的数据count++
            state.count++
        },
        // 接收参数
        setCount(state, num) {
            state.count = num
        },
        setMsg(state, msg) {
            state.msg = msg;
        }
    },
    // 执行mutations里的方法 异步操作放在actions里,调用: this.$store.dispatch("incCount")
    actions: {
        incCount(context) {
            context.commit("incCount"); // 执行mutations里的incCount方法
        },
        setMsg({commit}, msg) {
            setTimeout(() => {
                commit("setMsg", msg);  // 执行mutations里的setMsg方法
            }, 1000)
        }
    }
});
export default store;
组件中使用
<template>
    <h1>News组件</h1>
    <button @click="incCunt">调用Actions incCount</button>
    <br>
    <button @click="setMsg">调用Actions setMsg</button>
</template>

<!-- 设置语言为ts -->
<script>
    import {defineComponent} from 'vue'

    export default defineComponent({
        name: "News",
        methods: {
            incCunt() {
                this.$store.dispatch("incCount")
            },
            setMsg() {
                this.$store.dispatch("setMsg", "修改后的Msg")
            }
        }
    })
</script>

<style scoped>

</style>

1.7 modules

store.js
import {createStore} from 'vuex';
import newsStore from './newsStore';
import userStore from "@/vuex/userStore";

const store = createStore({
    modules: {
        // 调用state里的值:this.$store.state.user.count
        "user": userStore,
        "news": newsStore
    }
});

export default store;
userStore.js
let userStore = {
    // 定义数据 调用数据:this.$store.state.count;
    state() {
        return {
            count: 1,
            list: ["马总", "刘总", "李总"],
            msg: "你好Vue"
        }
    },
    // 定义方法 调用方法:this.$store.commit("incCount")
    mutations: {
        incCount(state) {
            // 使state里的数据count++
            state.count++
        },
        // 接收参数
        setCount(state, num) {
            state.count = num
        },
        setMsg(state, msg) {
            state.msg = msg;
        }
    },
    // 类似于computed属性 调用:this.$store.getters.reverseMsg
    getters: {
        reverseMsg(state) {
            return state.msg.split("").reverse().join("")
        },
        num(state) {
            return state.count + 10;
        }
    },
    // 执行mutations里的方法 异步操作放在actions里,调用: this.$store.dispatch("incCount")
    actions: {
        incCount(context) {
            context.commit("incCount"); // 执行mutations里的incCount方法
        },
        setMsg({commit}, msg) {
            setTimeout(() => {
                commit("setMsg", msg);  // 执行mutations里的setMsg方法
            }, 1000)
        }
    }
};

export default userStore;
newsStore.js
let newsStore = {
    // 定义数据 调用数据:this.$store.state.count;
    state() {
        return {
            list: ["新闻1", "新闻2", "新闻3"],
            count: 100
        }
    },
    mutations: {
        incCount(state) {
            state.count++;
        }
    }
};

export default newsStore;
组件中使用
<template>
    用户:<h1>Home组件 --- {{userCount}}</h1>
    新闻:<h1>Home组件 --- {{newsCount}}</h1>
    <button @click="incCount">调用module里incCount方法</button>
</template>

<script>
    import {defineComponent} from 'vue';

    export default defineComponent({
        name: "Home",
        methods: {
            incCount() {
                // 如果modules里的两个子module都有方法incCount,那么都会生效
                this.$store.commit("incCount");
            }
        },
        computed: {
            userCount() {
                // 获取stage中的user里的count值
                return this.$store.state.user.count;
            },
            newsCount() {
                // 获取stage中的news里的count值
                return this.$store.state.news.count;
            }
        }
    })
</script>

<style lang="scss" scoped>
</style>

二、Vuex结合composition API

store.js

import {createStore} from 'vuex';

const store = createStore({
    // 定义数据 调用数据:this.$store.state.count;
    state() {
        return {
            count: 1,
            list: ["马总", "刘总", "李总"],
            msg: "你好Vue"
        }
    },
    // 定义方法 调用方法:this.$store.commit("incCount")
    mutations: {
        incCount(state) {
            // 使state里的数据count++
            state.count++
        },
        // 接收参数
        setCount(state, num) {
            state.count = num
        },
        setMsg(state, msg) {
            state.msg = msg;
        }
    },
    // 类似于computed属性 调用:this.$store.getters.reverseMsg
    getters: {
        reverseMsg(state) {
            return state.msg.split("").reverse().join("")
        },
        num(state) {
            return state.count + 10;
        }
    },
    // 执行mutations里的方法 异步操作放在actions里,调用: this.$store.dispatch("incCount")
    actions: {
        incCount(context) {
            context.commit("incCount"); // 执行mutations里的incCount方法
        },
        setMsg({commit}, msg) {
            setTimeout(() => {
                commit("setMsg", msg);  // 执行mutations里的setMsg方法
            }, 1000)
        }
    }
});

export default store;

组件中使用

<template>
    <h1>Home组件 --- {{count}}</h1>
    调用getters的reverseMsg属性:{{reverseMsg}} <br>
    <button @click="incCount">调用mutations的incCount方法</button>
</template>

<script>
    import {defineComponent, computed} from 'vue';
    import {useStore} from 'vuex';

    export default defineComponent({
        name: "Home",
        setup() {
            // 获取store
            const store = useStore();

            // 获取stage里的值
            let count = computed(() => {
                return store.state.count;
            });

            // 定义方法
            let incCount = () => {
                // 调用mutations里的方法
                store.commit("incCount")
            };

            let reverseMsg = computed(() => {
                // 调用getters里的方法
                return store.getters.reverseMsg
            });

            return {count, incCount, reverseMsg}
        }
    })
</script>

<style lang="scss" scoped>
</style>

三、Vues集成Typescript

store.js改为store.ts

import {ComponentCustomProperties} from 'vue';
import {Store, createStore} from 'vuex';

// 配置vue+ts的项目里面使用vuex
declare module '@vue/runtime-core' {
    // declare your own store states
    interface State {  // 下面的state必须和该stage数据类型保持一致
        count: number,
        list: string[],
        msg: string
    }

    // provide typings for `this.$store`
    interface ComponentCustomProperties {
        $store: Store<State>
    }
}

const store = createStore({
    state() {
        return {
            count: 1,
            list: ["马总", "刘总", "李总"],
            msg: "你好Vue"
        }
    },
    // 定义方法 调用方法:this.$store.commit("incCount")
    mutations: {
        incCount(state: any) {
            // 使state里的数据count++
            state.count++
        },
        // 接收参数
        setCount(state: any, num) {
            state.count = num
        },
        setMsg(state, msg) {
            state.msg = msg;
        }
    },
    // 类似于computed属性 调用:this.$store.getters.reverseMsg
    getters: {
        reverseMsg(state: any) {
            return state.msg.split("").reverse().join("")
        },
        num(state: any) {
            return state.count + 10;
        }
    },
    // 执行mutations里的方法 异步操作放在actions里,调用: this.$store.dispatch("incCount")
    actions: {
        incCount(context) {
            context.commit("incCount"); // 执行mutations里的incCount方法
        },
        setMsg({commit}, msg) {
            setTimeout(() => {
                commit("setMsg", msg);  // 执行mutations里的setMsg方法
            }, 1000)
        }
    }
});

export default store;

组件中使用

// 和上面的用法一摸一样

<template>
    <h1>User组件 --- {{msg}}</h1>
</template>

<script lang="ts">
    import {defineComponent} from 'vue';

    export default defineComponent({
        name: "User",

        computed: {
            msg(): string {
                return this.$store.state.msg;
            }
        }
    })
</script>

<style lang="scss" scoped>
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值