Vue3中如何使用Pinia,Pinia基础入门教程,兄弟组件通信

Pinia基础入门教程

简介

Pinia 是 Vue.js 的状态管理库,它是 Vuex 的替代方案,在 2021 年左右推出,为 Vue 应用提供了一个简洁、高效的全局状态管理方式。

核心概念

  • State(状态)
    • 状态是应用中数据的来源。在 Pinia 中,state是一个响应式对象。例如,在一个简单的计数器应用中,状态可以存储计数器的当前值。
  • Getters(计算属性)
    • 类似于 Vue 组件中的计算属性,getters可以根据state的值派生出新的值。
    • getters是缓存的,只有当它所依赖的state发生改变时才会重新计算,这样可以提高性能。
  • Actions(动作)
    • actions是可以改变state的函数,它们可以是异步的。例如,在计数器应用中,可以定义一个action来增加计数器的值:

本文使用Vue3

使用Vue3脚手架

使用vite创建一个Vue项目

  1. 运行Vite创建命令
npm create vite@latest
  1. 填写项目名称

在这里插入图片描述

  1. 选择创建Vue项目

在这里插入图片描述

  1. 选择项目语言为JavaScript

在这里插入图片描述

  1. 创建成功

在这里插入图片描述

  1. 进入项目根目录,安装项目所需包

    npm i
    

    在这里插入图片描述

打开项目

  1. 本人比较喜欢WebStorm,一下操作均使用此IDE进行演示操作,也可使用VSCode等开发工具。

  2. 以上操作也可以用IDE本身自带的命令窗口进行创建,都没有区别

    在这里插入图片描述

    小技巧

    添加快速启动。

    在这里插入图片描述

    点击按钮即可启动

    在这里插入图片描述

安装Pinia

npm install pinia

在这里插入图片描述

具体使用

创建实例

创建一个 pinia 实例 (根 store) 并将其传递给应用:

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import {createPinia} from "pinia";
const pinia = createPinia()
const app=createApp(App)
app.use(pinia)
app.mount('#app')

定义 Store

  1. 创建store目录存放store

  2. 创建JS文件countStore

  3. 定义一个Store,根据官网提供的规范

    • 你可以任意命名 defineStore() 的返回值,但最好使用 store 的名字,同时以 use 开头且以 Store 结尾。

      import {defineStore} from 'pinia';
      
      export const useCounterStore = defineStore("counterDate", {
          state: () => ({
              count:0
          }),
      });
      
  • Store 是用 defineStore() 定义的,它的第一个参数要求是唯一的

  • defineStore() 的第二个参数可接受两类值:Setup 函数或 Option 对象。本文将采用Option 对象的形式

在App.vue中我们可以暂时使用这里定义的store

<script setup>
import {useCounterStore} from "./store/countStore.js";
const store = useCounterStore()
const count = store.count
</script>

<template>
  <div>
    <p>count的值</p> {{count}}
  </div>
</template>

<style scoped>

</style>

页面中我们可以看到count的值被正确的渲染出来

在这里插入图片描述

通过vue的浏览器工具,可以看到pinia的值并可以修改

在这里插入图片描述

Getter

Getter 完全等同于 store 的 state 的计算值。可以通过 defineStore() 中的 getters 属性来定义它们。推荐使用箭头函数,并且它将接收 state 作为第一个参数

  1. 定义Getters

    import {defineStore} from 'pinia';
    
    export const useCounterStore = defineStore("counterDate", {
        state: () => ({
            count:0
        }),
        getters:{
            doubleCount: (state) => state.count * 2
        }
    });
    

    大多数时候,getter 仅依赖 state。不过,有时它们也可能会使用其他 getter。因此,即使在使用常规函数定义 getter 时,我们也可以通过 this 访问到整个 store 实例但(在 TypeScript 中)必须定义返回类型。这是为了避免 TypeScript 的已知缺陷,不过这不影响用箭头函数定义的 getter,也不会影响不使用 this 的 getter

  2. 在App.vue中我们可以简单使用一下Getters

    <script setup>
    import {useCounterStore} from "./store/countStore.js";
    const store = useCounterStore()
    const increment=()=>{
      store.count++
    }
    </script>
    
    <template>
      <div>
        <button @click="increment">加一</button>
        <p>count的值</p> {{store.count}}
        <p>调用getter</p>{{store.doubleCount}}
      </div>
    </template>
    
    <style scoped>
    
    </style>
    

​ 通过点击我们可以看到count的值每次都加一,但是store.doubleCount的值每次都是count的二倍。

Actions

在上面的小例子中我们使用increment方法对count进行更改,但是如果多个页面需要对count进行更改,这样就需要定义多个方法,整体代码就不够优雅简洁。接下来我们定义一个actions来对state进行修改。

  1. 定义actions

    import {defineStore} from 'pinia';
    
    export const useCounterStore = defineStore("counterDate", {
        state: () => ({
            count:0
        }),
        getters:{
            doubleCount: (state) => state.count * 2
        },
        actions:{
            increment() {
                this.count++;
            }
        }
    });
    
  2. 在App.vue中进行简单使用

    <script setup>
    import {useCounterStore} from "./store/countStore.js";
    const store = useCounterStore()
    </script>
    
    <template>
      <div>
        <button @click="store.increment()">加一</button>
        <p>count的值</p> {{store.count}}
        <p>调用getter</p>{{store.doubleCount}}
      </div>
    </template>
    
    <style scoped>
    
    </style>
    

可以看到,和上面的效果是一样的。

不同页面中使用

通过上述的简单了解以及使用,可以发现,我们通过定义变量的方式也可以实现上述功能,就显得使用pinia有些许赘余,但是在父子组件,兄弟组件,甚至没有关系的组件中,我们都可以通过Store进行联系,接下来我将演示在兄弟组件中,使用pinia的方便快捷。

  1. 创建Home.vue文件

    <script setup>
    import {useLoginStore} from "../store/loginStore.js";
    import {useUserStore} from "../store/userStore.js";
    const store=useLoginStore()
    const userStore=useUserStore()
    </script>
    
    <template>
      <div>
        <span v-if="!store.isLogin">账号:{{userStore.userData.username}}</span>
        <br/>
        <button v-if="!store.isLogin" @click="store.login">登录</button>
      </div>
    </template>
    
    <style scoped>
    
    </style>
    
  2. 创建Login.vue文件

    <script setup>
    import {useLoginStore} from "../store/loginStore.js";
    import {ref} from "vue";
    
    const store = useLoginStore()
    const loginForm = ref({
      username:'',
      password:''
    })
    </script>
    
    <template>
      <div class="login-container">
        <h2>登录</h2>
        <form>
          <input type="text" v-model="loginForm.username" name ="username" placeholder="请输入用户名" required>
          <input type="password" v-model="loginForm.password" name="password" placeholder="请输入密码" required>
          <button @click="store.login(loginForm)">登录</button>
        </form>
      </div>
    </template>
    
    <style scoped>
    .login-container{
      border: 1px solid green;
    }
    </style>
    
  3. 创建loginStore.js

    import {defineStore} from 'pinia';
    import { useUserStore } from './userStore';
    export const useLoginStore = defineStore("loginStore", {
        state: () => ({
            isLogin:false
        }),
        actions:{
            login(data) {
                this.isLogin=!this.isLogin
                const userStore = useUserStore()
                userStore.setData(data);
            }
        }
    });
    
  4. 创建userStore.js

    import {defineStore} from 'pinia';
    
    export const useUserStore = defineStore("userStore", {
        state: () => ({
            userData:{}
        }),
        actions:{
            setData(data) {
                this.userData=data
            }
        }
    });
    
  5. 编写App.vue

    <script setup>
    import Login from "./components/Login.vue";
    import Home from "./components/Home.vue";
    import {useLoginStore} from "./store/loginStore.js";
    const store = useLoginStore()
    </script>
    
    <template>
      <div>
        <Home/>
        <Login v-if="store.isLogin"/>
      </div>
    </template>
    
    <style scoped>
    
    </style>
    

这段代码简单描述了兄弟组件相互调用以及数据共享的相关方法,相对与通过中间组件完成兄弟组件的通信更加简单。

在这里插入图片描述

结语

Pinia还有很多使用方法,例如订阅 、持久化插件等等。详情可查看Pinia官网。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值