Pinia使用详解(vue3默认状态管理)

1 篇文章 0 订阅
1 篇文章 0 订阅

vue3-vite-less-配置别名-多环境_链接地址
vue3 路由和状态管理(pinia)传送门
pinia用法分为两种: options AIP, composition AIP 分别对应了vue的option 写法和 setup 写法(piniay option api 写法也支持在 vue setup中使用)
官网的建议
当不知道使用哪种方式的时候,官网建议我们首先使用 options Api
下面我们开始探讨两种方式的用法和区别(vue3)

Option API

安装pinia

执行 npm install pinia, 由于是新建的vue3项目,直接安装默认最新稳定版本就可以, 如果有同学需要学习用法,建议还是下载最新版本学习,不存在版本兼容问题

创建pinia

在 src 目录下,新建 store/index.ts。其中代码如下

import { createPinia } from "pinia";
// 创建pinia
export const store = createPinia();

在 src/main.ts 文件中引入

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
// 导入pinia
import { pinia } from './store'
createApp(App)
.use(pinia)
.use(ElementPlus)
.mount('#app')

这样就将pinia 引入到项目中,pinia的用法和vueX的用法不太一样。导入的pinia并不是存放状态(state)、getter、actions的。下面开始正式进入option api的介绍。

使用option Api 创建store

接着在 src/sotre/index.ts中增加代码

import { createPinia, defineStore } from "pinia";
// 创建pinia
export const pinia = createPinia();
/**
 * 创建一个store使用函数,
 * defineStore 调用,并不会真正创建一个store,
 * 只用在使用的时候(调用 userHandlerInfo())的时候,
 * 才会真正创建store。
 * 所在,在命名的时候 使用 use功能名称, 
 * 需要创建store时: const store = user功能名称();
 */
export const useHandlerInfo = defineStore("USER_INFO", {
    // 通过箭头函数返回一个初始化的状态 option api 定义只有这种写法
    state: () => {
        return {
            name: "王日天",
            phone: "18888888",
        }
    },
    // 定义获取状态的方法
    getters: {
        /**
         * 传入state,通过state 获取状态
         * 通过state获取的时候可以使用箭头函数
         * @param state 
         * @returns 
         */
        getName: (state) => {
            return state.name;
        },
        /**
         * 什么都不传入,直接通过this 获取状态
         * 通过this获取不能使用箭头函数,
         * 其中的this就是 store实例
         */
        getPhone(): string{
           return this.phone;
        }
    },
    // 修改state 的方法
    actions: {
        /**
         * 通过外界传来的 name,赋值给store中的name
         * 其中的this 也是 store 实例
         * @param name 
         */
        setName(name: string){
            this.name = name;
        },
        setPhone(p: string){
            this.phone = p;
        }
    }
})

注释要比代码多,
defindStore接受两个参数,第一个参数为 id, 这个参数是必须要的,pinia通过这个id来连接开发工具。第二个参数,用来配置store。
defindStore 并不会直接创建 store, 只有在使用 use***()方法的时候,才会真正创建一个store
在这里插入图片描述
getters 和 actions中的this 就是创建成store之后的实例
在这里插入图片描述
到这里,一个使用option api 定义的store 就完成了。

读取,修改store中的数据

修改App.vue中的代码
导入src/store/index.ts 中定义的 userHandlerInfo。

使用mapState 读取数据,mapActions修改数据(和vueX差不多)
<script lang="ts">
//导入user***
import { useHandlerInfo } from "@/store"
import { mapActions, mapState } from "pinia";
export default {
    data() {
        return {}
    },
    computed: {
        ...mapState(useHandlerInfo, ['name', 'phone']),
        ...mapState(useHandlerInfo, {
            // // 通过mapState 取别名获取
            alias: 'name',
            // 自定义函数获取
            toFormat: (store) => {
                const phone = store.getPhone;
                return phone + "通过方法转换";
            }

        })
    },
    methods: {
        ...mapActions(useHandlerInfo, ['setName', 'setPhone']),
        // 通过别名获取 actions中的方法
        ...mapActions(useHandlerInfo, {setAlias: 'setName'}),
    },
    mounted(){
        setTimeout(() => {
            this.setName("张三丰");
            this.setPhone("732432488");
            console.log(this.name);   
        }, 2000);
        setTimeout(() => {
            this.setAlias("武当掌门 张三丰");
        }, 5000)
    }
}
</script>
<template>
    <div class="show-content">内容展示区域
        <div>{{name}}</div>
        <div>{{phone}}</div>
        <div>{{alias}}</div>
        <div>{{toFormat}}</div>
    </div>
</template>

<style scoped lang="less">
.show-content {
    color: #333;
    font-size: 14px;
    background: rgb(110, 166, 204);
}
</style>

查看页面结果
在这里插入图片描述

在setup() 函数中使用store
<script lang="ts">
//导入user***
import { useHandlerInfo } from "@/store"
import { mapActions, mapState } from "pinia";
import { onMounted } from "vue";
export default {
    setup() {
        const store = useHandlerInfo();
        onMounted(() => {
            setTimeout(() => {
                // 修改数据
                store.setName("张三丰");
                store.setPhone("80909889")
            }, 3000)
        })
        return {
            store,
        }
    }
}
</script>
<template>
    <div class="show-content">内容展示区域
        // 读取数据
        <div>{{store.getName}}</div>
        <div>{{store.getPhone}}</div>
    </div>
</template>

<style scoped lang="less">
.show-content {
    color: #333;
    font-size: 14px;
    background: rgb(110, 166, 204);
}
</style>
通过在 script 中加 setup来使用 sotre(极简模式,vue3,推荐优选选择这种写法)
<script lang="ts" setup>
//导入user***
import { useHandlerInfo } from "@/store"
import { onMounted } from "vue";
const store = useHandlerInfo();
// 对应vue2 的mouted 生命周期
onMounted(() => {
    setTimeout(() => {
        store.setName("张三丰 飞升成仙");
        store.setPhone("9874354")
    }, 5000)
})
</script>
<template>
    <div class="show-content">内容展示区域
        // 读取数据
        <div>{{store.getName}}</div>
        <div>{{store.getPhone}}</div>
    </div>
</template>

<style scoped lang="less">
.show-content {
    color: #333;
    font-size: 14px;
    background: rgb(110, 166, 204);
}
</style>

可以看到setup 中也可以使用 option api创建的 store。并且使用方法要比option api 创建的vue简单。其中在script 标签上 加入 setup, 直接在script 书写逻辑,是最简单的。
这就是options Api 创建 store 的使用

Composition API 创建store

pinia 的安装和引入都是和 options api一样的

定义store

继续在scr/store/index.ts里面添加一个use***的声明

import { createPinia, defineStore } from "pinia";
import { computed, ref } from "vue";
// 创建pinia
export const pinia = createPinia();
/**
 * 使用 composition API 定义store
 * 第一个参数是 id, 第二个参数是一个函数 
 * 在这种语法中,第二个参数变成了一个函数,
 * 函数里面 的 ref 变成了 options API 里面的state,
 * 里面的 computed 变成了 options API 里面额 getter
 * 里面的 function 变成了 options API 里面的 action
 * 
 * 最后一步,一点过要把这些声明返回来
 */
export const useUserInfo = defineStore("USER_INFO_2", () => {
    // 使用 ref 创建一个 状态
    const age = ref(99);
    const sex = ref("人妖");
    // 使用 computed 创建一个 getter
    const getAge = computed(() => age);
    const getSex = computed(() => sex);
    // 使用function 创建一个 action
    function setAge(a: number) {
        age.value = a;
    }
    function setSex(s: string){
        sex.value = s;
    }
    return {age, sex, getAge, getSex, setAge, setSex};
})

可以看到 composition Api 的定义store 和 option api 定义完全不一样。composition Api 定义store的时候用到了vue 包里面的 ref, computed。其中
在这里插入图片描述
把官网中的描述,抄写到注释里面了。

读取,修改store中的数据

继续在App.vue文件中进行操作, 导入刚刚在src/store/index.ts 文件加中声明的 useUserInfo(使用 用户信息 use***)。

在javascript 标签中 加setup 使用,
<script lang="ts" setup>
//导入user***
import { useHandlerInfo, useUserInfo } from "@/store"
import { onMounted } from "vue";
// options api 定义的store
const store = useHandlerInfo();
// composition api 定义的store
const userStore = useUserInfo();
// 对应vue2 的mouted 生命周期
onMounted(() => {
    setTimeout(() => {
        // option api 定义的 store 修改数据
        store.setName("张三丰 飞升成仙");
        store.setPhone("9874354")

        // composition api 定义的store 修改数据
        userStore.setAge(88);
        userStore.setSex("泰国人妖");
    }, 5000)
})
</script>
<template>
    <div class="show-content">内容展示区域
        // 读取数据
        <div>{{store.getName}}</div>
        <div>{{store.getPhone}}</div>
        composition api 定义的store 获取数据
        <div>age: {{userStore.getAge}}</div>
        <div>sex: {{userStore.getSex}}</div>
    </div>
</template>

<style scoped lang="less">
.show-content {
    color: #333;
    font-size: 14px;
    background: rgb(110, 166, 204);
}
</style>

可以看到使用的时候,和options api 声明的store在javascript 中添加setue使用差不多

使用 setup() 方法来使用

代码如下,

<script lang="ts">
//导入user***
import { useHandlerInfo, useUserInfo } from "@/store"
export default{
    setup(){
                // options api 定义的store
        const store = useHandlerInfo();
        // composition api 定义的store
        const userStore = useUserInfo();
        return {
            store,
            userStore,
        }
    },
    mounted() {
        setTimeout(() => {
        // option api 定义的 store 修改数据
        this.store.setName("张三丰 飞升成仙");
        this.store.setPhone("9874354")

        // composition api 定义的store 修改数据
        this.userStore.setAge(88);
        this.userStore.setSex("泰国人妖");
    }, 5000)
    }
}
</script>
<template>
    <div class="show-content">内容展示区域
        // 读取数据
        <div>{{store.getName}}</div>
        <div>{{store.getPhone}}</div>
        composition api 定义的store 获取数据
        <div>age: {{userStore.getAge}}</div>
        <div>sex: {{userStore.getSex}}</div>
    </div>
</template>

<style scoped lang="less">
.show-content {
    color: #333;
    font-size: 14px;
    background: rgb(110, 166, 204);
}
</style>

可以看到使用的时候,和options api 声明的store在setue()函数中使用差不多。
compostion api 声明的store 能否在 option 方式定义的 Vue组件中使用,官网上没有看到明确的说明(也可能是我看漏了,大家可以去看看,记得回来告诉我)

storeToRefs

在setup中使用 store的时候,前面我们一直是返回的整个stroe,
在这里插入图片描述
有时候,我们需要使用单个属性,就需要用到 storeToRefs
使用方式如下

    setup(){
        // composition api 定义的store
        const userStore = useUserInfo();
        // 返回单个属性,并保持响应式
        // 千万不要使用 es6 的解构赋值,es6 解构赋值之后,会取消响应式
        const {getAge, getSex} = storeToRefs(userStore);
        return {
            userStore,
            getAge,
            getSex,
        }
    },

然后就可以在代码中使用 getAge, getSex,和声明在 setUp()中的属性一样使用
我们照例贴上官网权威说明, 其中最重要的两句,已经圈出来, only using state(没法使用 actions里面的方法);keeipng its reactivity (保持响应式, store中数据变化之后,使用数据的地方自动改变)
在这里插入图片描述
option api 定义的store 和 composition api定义的 store,都可以使用 storeTorefs();
需要注意的是只能在 setup() 方法中使用, 或者在javascript 标签上加了setup 的组件上使用

类型声明,类型声明需要熟悉ts

类型声明和ts类型声明一样,直接弄上官网连接和图
在这里插入图片描述
在这里插入图片描述
两种类型声明都比较简单。
pinia 的基本使用方法,也就介绍完成了。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Pinia是Vue的官方状态管理库,用于在Vue3项目中实现数据共享。下面是使用Pinia的基本步骤: 1. 安装Pinia:在Vue3项目中,使用npm或yarn安装Pinia库。 2. 创建Pinia实例:在项目的入口文件中,创建一个Pinia实例并将其导出。 3. 定义状态:在需要共享状态的组件中,使用`defineStore`函数定义一个状态存储对象。 4. 注册状态:在组件中使用`useStore`函数注册状态,并在模板中使用。 5. 使用状态:在组件中可以通过`$store`访问状态,并在模板中使用。 下面是一个使用Pinia的示例代码: ```javascript // main.js import { createApp } from 'vue' import { createPinia } from 'pinia' import App from './App.vue' const app = createApp(App) const pinia = createPinia() app.use(pinia) app.mount('#app') // store.js import { defineStore } from 'pinia' export const useCounterStore = defineStore('counter', { state: () => ({ count: 0 }), actions: { increment() { this.count++ }, decrement() { this.count-- } } }) // Counter.vue <template> <div> <p>Count: {{ $store.counter.count }}</p> <button @click="$store.counter.increment()">Increment</button> <button @click="$store.counter.decrement()">Decrement</button> </div> </template> <script> import { useCounterStore } from './store' export default { setup() { const counterStore = useCounterStore() return { counterStore } } } </script> ``` 在上面的示例中,我们首先在`main.js`中创建了一个Pinia实例,并将其应用于Vue应用。然后,在`store.js`中定义了一个名为`counter`的状态存储对象,其中包含一个名为`count`的状态和两个操作。最后,在`Counter.vue`组件中使用`useCounterStore`函数注册状态,并在模板中使用`$store.counter.count`访问状态

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值