Pinia入门

267 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情 当Vue3成为正式版后,pinia作为一个全新的状态管理库是尤大主要强推的项目, 还有就是与vuex相比较来说pinia拥有了更简单的api,更少的规范等等。 这也是我为什么来学习的原因啦~ 虽然算不上尤大的粉,但也是我的崇拜者~😜

pinia 优点

1、支持vue2、vue3

2、抛弃mutations操作,只有state、gettersactios

3、不需要嵌套模块,符合Vue3Composition api;

4、完整的ts支持;

5、代码简洁;

使用

  • 所用技术栈:vue3 + ts + vite 构建基础上使用pinia

  • 安装:yarn add pinia

  • 创建文件

    src目录下创建store 文件夹

    store文件夹中创建index.ts文件

  • 目的: 定义状态容器和数据、修改容器中的state、仓库中action的使用

  • 用法:index.ts文件中需要从pinia中引入defineStore

    1、defineStore 需要传递两个参数 id名称(string类型) 、 配置项(Obiect类型)

    2、id名称必填,不然会报错

    3、配置项是一个对象,其中有以下属性

       export const mainStore = defineStore('main', {
           state: () => {
               return {}
           },
           geeters: {},
           actions: {}
       })
    

    state: 定义需要被监听的数据变化

    getters:计算属性 计算属性存在缓存的,当多次调用未修改的数据,其实getters里面是只调用了一次的(比较好的性能优化)

    actions:可以在里面写复杂的逻辑业务

  • store中数据的几种方式:

在需要使用这些数据的页面里面进行操作

首先需要利用storeToRefsstore里面的数据解构为响应式数据

import {mainStore} from './store/index'
import {storeToRefs} from 'pinia' // 利用storeToRefs将store里面的数据解构为响应式数据
const store = mainStore();
const {helloWord, count, phoneHide} = storeToRefs(store);

1、直接对store中数据进行修改

let handleAdd = () => {
  store.count++; // 改变的是状态数据
  store.helloWord = store.helloWord === 'jxx' ? 'hello word' : 'jxx';
}

2、 通过$patch传递对象进行多数据修改。其实也可以通过第一种方式对数据进行改变,不过官方给出的建议是在进行多数据改变的时候尽量使用此方法,因为此方法是经过官方优化的。

let handlePatch = ()=> {
  store.$patch({
    count:store.count+2,
    helloWord: store.helloWord === 'jxx' ? 'hello word' : 'jxx'
  })
}

3、使用$patch 传递函数 常用于处理复杂逻辑

let handleMethod = () => {
   store.$patch((state) => { // state为数据仓库中的state
      state.count++;
      state.helloWord = state.helloWord === 'jxx' ? 'hello word' : 'jxx';
   })
}

4、通过store中的actions 常用于业务逻辑及其复杂,需要写在actions里面

 actions: {
    // 不能使用箭头函数,this会指向最外层
    handleAction() {
      this.count++;
      this.helloWord = 'jxx' ? 'hello word' : 'jxx';
    }
  }

具体代码

main.ts的代码

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

index.ts文件

import {defineStore} from 'pinia'
// defineStore 需要传递两个参数 id名称 、 配置项
export const mainStore = defineStore('main', {
  state: () => { // 定义数据
    return {
      helloWord: 'hello word',
      count: 0,
      phone: '15639549985',
    }
  },
  getters: {// 计算属性 是有缓存的 如果多次调用数据并没有改变 那么其实是只调用一次的(性能优化)
    phoneHide(state) { // 如果不传state,那么通过this也是可以获取phone的值的 但是ts无法对数据类型进行推导会报错 解决:phoneHide(): String {}
      return state.phones.toString().replace(/^(\d{3})\d{4}(\d{4})$/,'$1****$2')
    }
  }, // 监听数据变化
  // 4、第四种 业务逻辑及其复杂,需要写在actions里面
  actions: {
    // 不能使用箭头函数,this会指向最外层
    handleAction() {
      this.count++;
      this.helloWord = 'jxx' ? 'hello word' : 'jxx';
    }
  }
})

App.vue中测试一下

<template>
    <div>
      <div>{{helloWord}}</div>
      <button @click="handleAdd()">+</button>
      <button @click="handlePatch()">+2</button>
      <button @click="handleMethod()">+1</button>
      <button @click="handleActions()">+1actions</button>
      <div>{{count}}</div>
      <div>{{phoneHide}}</div>
    </div>
</template>
<script setup lang="ts">
import {mainStore} from './store/index'
import {storeToRefs} from 'pinia' // 利用storeToRefs将store里面的数据解构为响应式数据
const store = mainStore();
const {helloWord, count, phoneHide} = storeToRefs(store);
// 状态值修改的几种方式
// 1、第一种
let handleAdd = () => {
  store.count++; // 改变的是状态数据
  store.helloWord = store.helloWord === 'jxx' ? 'hello word' : 'jxx';
}
// 2、第二种$patch 传递对象
// 好处:多数据修改(官方给出此方法经过优化,适用于多数据改变)
let handlePatch = ()=> {
  store.$patch({
    count:store.count+2,
    helloWord: store.helloWord === 'jxx' ? 'hello word' : 'jxx'
  })
}
// 3、第三种$patch 传递函数 常用于处理复杂逻辑
let handleMethod = () => {
   store.$patch((state) => { // state为数据仓库中的state
      state.count++;
      state.helloWord = state.helloWord === 'jxx' ? 'hello word' : 'jxx';
   })
}
// 4、第四种 通过actions
let handleActions = () => {
  store.handleAction()
}
</script>

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