vue3+Pinia的使用

2 篇文章 0 订阅

Pinia官网地址

https://pinia.vuejs.org/

Pinia的优势

Pinia是一个全新的Vue状态管理库,是Vuex的代替者,尤雨溪强势推荐

  1. Vue2 和 Vue3 都能支持
  2. 抛弃传统的 Mutation ,只有 state, getter 和 action ,简化状态管理库
  3. 不需要嵌套模块,符合 Vue3 的 Composition api,让代码扁平化
  4. TypeScript支持
  5. 代码简洁,很好的代码自动分割

Pinia的基本使用

初始化项目

npm init vite@latest

安装

npm install pinia
yarn add pinia

挂载Pinia

// src/main.ts
import { createPinia } from 'pinia'
const pinia = createPinia()
createApp(App).use(pinia).mount('#app')

创建store

//  src/store/index.ts

import { defineStore } from "pinia";
export const mainStore = defineStore("main", {
  state: () => {
    return {
      msg: "hello world",
    };
  },
  getters: {},
  actions: {},
});

注:这是官网上提供的常规写法,我个人还是更偏向于下面这种写法:

//  src/store/index.ts

import { defineStore } from "pinia";

interface State {
  msg: string;
  count: number;
}

const defaultState:State = {
  msg: "hello world!"
}

export const mainStore = defineStore("main", {
  state: () => {
    return defaultState;
  },
  getters: {},
  actions: {},
  },
});

使用Store

//  src/components/HelloWorld.vue

<script setup lang="ts">
import { mainStore } from '../store';
const store = mainStore()
</script>

<template>
  <h1>{{store.msg}}</h1>
</template>

<style scoped>

</style>

解构store

当store中的多个参数需要被使用到的时候,为了更简洁的使用这些变量,我们通常采用结构的方式一次性获取所有的变量名

  • ES传统方式解构(能获取到值,但是不具有响应性)
//  src/components/HelloWorld.vue

<script setup lang="ts">
import { mainStore } from '../store';
const store = mainStore()
const {count} = store
</script>

<template>
  <p>正常获取--{{store.count}}</p>
  
  <p>ES传统方式解构,count不会响应式更新--{{count}}</p>
  
  <h1>{{store.msg}}</h1>
</template>

<style scoped>

</style>

在这里插入图片描述

点击按钮,count的值+1,可以看到传统方式解构,count不会响应式更新。那要怎么解构呢?Pinia给我们提供了一个解构方法:

  • Pinia解构方法:storeToRefs
//  src/components/HelloWorld.vue

<script setup lang="ts">
import { mainStore } from '../store';
import {storeToRefs} from 'pinia'
const store = mainStore()
// const {count} = store
const {count} = storeToRefs(store)
</script>

<template>
  <p>正常获取--{{store.count}}</p>
  
  <!-- <p>ES传统方式解构,count不会响应式更新--{{count}}</p> -->

  <p>Pinia中的storeToRefs方法解构,count可以响应式更新--{{count}}</p>
  
  <h1>{{store.msg}}</h1>
</template>

<style scoped>

在这里插入图片描述

Pinia修改数据状态

  • 简单数据修改

简单数据直接通过在方法中操作 store.属性名 来修改

<script setup lang="ts">
import HelloWorld from './components/HelloWorld.vue'
import { mainStore } from './store';
const store = mainStore()

const addOne = ():void => {
  store.count++
}
</script>

<template>
  <button @click="addOne">点击+1</button>
  <HelloWorld/>
</template>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
  • 多条数据修改

通过基础数据修改方式去修改多条数据也是可行的,但是在 pinia 官网中,已经明确表示$patch的方式是经过优化的,会加快修改速度,对性能有很大好处,所以在进行多条数据修改的时候,更推荐使用 $patch

$patch 方法可以接受两个类型的参数,函数 和 对象

  1. $patch + 对象
  2. $patch + 函数: 通过函数方式去使用的时候,函数接受一个 state 的参数,state 就是 store 仓库中的 state
<script setup lang="ts">
import { mainStore } from './store';
const store = mainStore()

// $path + 对象
const onObjClick = ():void => {
  store.$patch({
    count: store.count + 2,
    msg: store.msg === 'hello world!' ? '你好 世界!' : 'hello world!'
  })
}

// $patch + 函数
const onFunClick = ():void => {
  store.$patch((state) => {
    state.count += 2
    state.msg = store.msg === 'hello world!' ? '你好 世界!' : 'hello world!'
  })
}

</script>

<template>
  <div>
    <button @click="onObjClick">修改所有状态($patch + 对象)</button>
    <button @click="onFunClick">修改所有状态($patch + 函数)</button>
  </div>
</template>
  • 通过action修改
  1. Store.actions中添加 changeState 方法
import { defineStore } from "pinia";
import { reactive } from "vue";

interface State {
  msg: string;
  count: number;
}

const defaultState:State = {
  msg: "hello world!",
  count: 0,
}

export const mainStore = defineStore("main", {
  state: () => {
    return defaultState;
  },
  getters: {},
  actions: {
    changeState() {
        this.count++;
        this.msg = this.msg === "hello world!" ? "你好 世界!" : "hello world!";
    },
  },
});
  1. 组件方法调用 store.方法名
<script setup lang="ts">
import { mainStore } from './store';
const store = mainStore()

// 通过action修改多个状态
const onActionClick = ():void => {
  store.changeState()
}

</script>

<template>
  <div>
    <button @click="onActionClick">修改多个状态(action)</button>
  </div>
</template>

Pinia中的Getters

Pinia 中的 getter 和 Vue 中的计算属性几乎一样,在获取 State值之前做一些逻辑处理。
getter中的值有缓存特性,如果值没有改变,多次使用也只会调用一次

  • 添加 getter方法
import { defineStore } from "pinia";
import { reactive } from "vue";

interface State {
  msg: string;
  count: number;
}

const defaultState = reactive<State>({
  msg: "hello world!",
  count: 0,
})

export const mainStore = defineStore("main", {
  state: () => {
    return defaultState;
  },
  getters: {
      getState(state) {
          console.log('getter被调用');
          return `${state.msg}---${state.msg}`
      }
  },
  actions: {
    changeState() {
        this.count++;
        this.msg = this.msg === "hello world!" ? "你好 世界!" : "hello world!";
    },
  },
});
  • 组件内多次调用
<script setup lang="ts">
import { mainStore } from './store';
const store = mainStore()
</script>

<template>
  <div>
    <hr />
    <h1>Getter 获取数据</h1>
    <div>{{store.getState}}</div>
    <div>{{store.getState}}</div>
    <div>{{store.getState}}</div>
    <div>{{store.getState}}</div>
    <div>{{store.getState}}</div>
  </div>
</template>

在这里插入图片描述

  • getter 中不仅可以传递 state 直接改变数据状态,还可以使用 this 来改变数据
import { defineStore } from "pinia";

interface State {
  msg: string;
  count: number;
}

const defaultState: State = {
    msg: "hello world!",
    count: 0,
  }

export const mainStore = defineStore("main", {
  state: () => {
    return defaultState;
  },
  getters: {
      getState():string {
          console.log('getter被调用');
          return `${this.msg}---${this.msg}`
      }
  },
  actions: {
    changeState() {
        this.count++;
        this.msg = this.msg === "hello world!" ? "你好 世界!" : "hello world!";
    },
  },
});

store之间的相互调用

Pinia 中,可以在一个 storeimport 另外一个 store ,然后通过调用引入 store 方法的形式,获取引入store 的状态

  • 新建 store
// src/store/music.ts
import { defineStore } from "pinia";

interface State {
  list: string[];
}

const defaultState: State = {
  list: ['晴天', '枫', '以父之名', '手写的从前', '明明就', '半岛铁盒', '稻香', '最长的电影']
};

export const musicStore = defineStore("music", {
  state: () => {
    return defaultState;
  },
  getters: {},
  actions: {},
});
  • 在原 store 中引入 musicStore,并获取 list
// src/store/index.ts

import { defineStore } from "pinia";
import {musicStore} from './music'

interface State {
  msg: string;
  count: number;
}

const defaultState: State = {
    msg: "hello world!",
    count: 0,
  }

export const mainStore = defineStore("main", {
  state: () => {
    return defaultState;
  },
  getters: {
    getState():string {
        console.log('getter被调用');
        return `${this.msg}---${this.msg}`
    },
    //   另一个Store引用,获取musicStore中的list
    getMusicStoreList(): string[] {
        return musicStore().list
    }
  },
  actions: {
    changeState() {
        this.count++;
        this.msg = this.msg === "hello world!" ? "你好 世界!" : "hello world!";
    },
  },
});
  • 组件中使用
<script setup lang="ts">
import HelloWorld from './components/HelloWorld.vue'
import { mainStore } from './store';
const store = mainStore()
</script>

<template>
  <div>
    <hr />
    <h1>Store 互相调用</h1>
    <ul>
      <li v-for="item in store.getMusicStoreList" :key="item">{{item}}</li>
    </ul>
  </div>
</template>

在这里插入图片描述

总结

总得来说,Pinia 就是 Vuex 的替代版,可以更好的兼容 Vue2,Vue3以及TypeScript。
在Vuex的基础上去掉了 Mutation,只保留了 state, getter和action。
Pinia拥有更简洁的语法, 扁平化的代码编排,符合Vue3 的Composition api

当然,文章中如果有什么错误或不足,欢迎评论区指正!

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bigHead-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值