Pinia

1.Pinia与vuex的比较

随着vue的更新,vuex已经更新到了vuex5的版本,此时我们意识到Pinia已经实现了vuex5中想要的大部分内容,因此决定实现Pinia取代vuex。与vuex相比,Pinia提供了一个更简单的API,具有更少的规范,提供了Composition-API的风格,最重要是在于TypeScrpit一起使用时具有可靠的类型推断支持。

Pinia API 与 Vuex ≤4 有很大不同,即:

  • mutations 不再存在。他们经常被认为是 非常 冗长。他们最初带来了 devtools 集成,但这不再是问题。
  • 无需创建自定义复杂包装器来支持 TypeScript,所有内容都是类型化的,并且 API 的设计方式尽可能利用 TS 类型推断。
  • 不再需要注入、导入函数、调用函数、享受自动完成功能!
  • 无需动态添加 Store,默认情况下它们都是动态的,您甚至都不会注意到。请注意,您仍然可以随时手动使用 Store 进行注册,但因为它是自动的,您无需担心。
  • 不再有 modules 的嵌套结构。您仍然可以通过在另一个 Store 中导入和 使用 来隐式嵌套 Store,但 Pinia 通过设计提供平面结构,同时仍然支持 Store 之间的交叉组合方式。 您甚至可以拥有 Store 的循环依赖关系
  • 没有 命名空间模块。鉴于 Store 的扁平架构,“命名空间” Store 是其定义方式所固有的,您可以说所有 Store 都是命名空间的。

2.核心概念

(1)定义pinia根存储

在main.ts 中设置

import { createPinia } from 'pinia'

const app = createApp(App)
app.use(createPinia())

app.mount('#app')

(2)使用store

import {defineStore} from 'pinia';

// 第一个参数是引用成俗中store的唯一id
export const useStore = defineStore('main', {
  // other opition ...
})
import {useStore} from '@/stores'

const store = useStore();
console.log(store); // store可在实例模板中使用

// 注意:store不支持解构写法,否则会失去响应式
// 如果想从store中提取出属性相同的数据并保持响应式,则需要使用storeToRefs()或者使用toRefs()
import { storeToRefs } from 'pinia';
const store = useStore();
const { name, doubleCount } = storeToRefs(store);
console.log(name, doubleCount);

(3)state数据

state是vue存储库的中心,可以时间跨页面多组件之间的数据共享

①组合式api(Setup Stores)

写法介绍:

// 定义组合式api的pinia数据
export const useCounterStore = defineStore('counter', () => {
  // state数据
  const count = ref(0)
  const name = ref('Eduardo')
  
  // getters计算属性
  const doubleCount = computed(() => count.value * 2)
  
  // action函数方法
  function increment() {
    count.value++
  }

  return { count, name, doubleCount, increment }
})

// 使用组合式api的pinia
import {useCounterStore} from '@/stores/counter'
const conter = useCounterStore()

数字:{{conter.count}}
姓名:{{conter.name}}
二倍:{{conter.doubleCount}}

②选项式api(Option Stores)

写法介绍:

export const useCounterStore = defineStore('counter', {
  // state数据
  state: () => ({ count: 0, name: 'Eduardo' }),
  // getters计算属性
  getters: {
    doubleCount: (state) => state.count * 2,
  },
  // action函数方法
  actions: {
    increment() {
      this.count++
    },
  },
})

(4)state的修改与替换($patch方法)

①$patch的使用场景

当需要同时修改多个state属性时,可以使用$patch方法

import useStore from '@/stores'
const store = useStore()
store.$patch({
  count: store.count + 1,
  age: 12,
  name: 'DIO'  
})

②$patch的函数参数用法

import useStore from '@/stores'
const cartStore = useStore()
cartStore.$patch((state) => {
    state.items.push({ name: 'shoes', quantity: 1 })
    state.hasChanged = true
})

③替换state

store.$state = { count: 24 }
store.$patch({ count: 24 })

(5)state的重置

选项式api下state的重置:

store.$reset()

组合式api下state的重置:

setup api下不能使用 $reset 方法
会报错: Store "xxx" is built using the setup syntax and does not implement $reset()


需要在main.ts文件中给pinia设置$reset
import { createPinia } from 'pinia'

const app = createApp(App)
const pinia = createPinia();
    
pinia.use(({ store }) => {
  const initialState = JSON.parse(JSON.stringify(store.$state))
  store.$reset = () => {
    store.$state = JSON.parse(JSON.stringify(initialState))
  }
})

app.use(pinia)

(6)state订阅更新($subscribe使用)

import useStore from '@/stores'

const store = useStore()
store.$subscribe((mutation, state) => {
    // mutation:是记录state变化信息的对象
    // state:是store的state对象
    console.log(mutation, state)
    
    // import { MutationType } from 'pinia'
    mutation.type // 'direct' | 'patch object' | 'patch function'
    
    // 与 cartStore.$id 相同,
    mutation.storeId // 'cart'
    
    // 仅适用于 mutation.type === 'patch object'
    mutation.payload // 补丁对象传递给 to cartStore.$patch()
  
    // 每当它发生变化时,将整个状态持久化到本地存储
    localStorage.setItem('cart', JSON.stringify(state))
})

注意事项:

$subscribe() 与 watch()的区别

$subscribe是$patch执行就会触发(无论值是否真的改变了),而watch是监听对象(值)改变才会触发。

(7)getters的使用

getters可以理解为storestate的计算属性

采用setup aoi的形式(组合式api)

定义:
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'

export const userStore = defineStore('user', () => {
  const nick = ref('小明');
  const codes = ref([80]);

  // 此处即为getters
  const msg = computed(() => {
    return '昵称:' + nick.value + ', 得分:' + codes.value
  })
  
  return { nick, codes, msg }
})

使用:
import { userStore } from '@/stores/user';
import { toRefs } from 'vue';
const user = userStore()
const { nick, codes, msg } = toRefs(user);

{{msg}}
// 此处为 pinia中的msg信息

(8)actions的使用

actions可以理解为store中的methods(也就是函数)

采用setup aoi的形式(组合式api)

定义:
import { ref } from 'vue'
import { defineStore } from 'pinia'

export const userStore = defineStore('user', () => {
  const codes = ref(58);

  // 定义actions
  function renderCode () {
    codes.value = Math.floor(Math.random() * 100)
  }
  return { codes, renderCode }
})

使用:
import { userStore } from '@/stores/user';
import { toRefs } from 'vue'
const { renderCode } = toRefs(userStore());

(9)插件plugins的使用

import { createPinia } from 'pinia'

// 为安装此插件后创建的每个store添加一个名为 `secret` 的属性
// 这可能在不同的文件中
function SecretPiniaPlugin() {
  return { secret: 'the cake is a lie' }
}

const pinia = createPinia()
// 将插件提供给 pinia
pinia.use(SecretPiniaPlugin)

// 在另一个文件中
const store = useStore()
store.secret // 'the cake is a lie'

3.pinia持久化存储

采用插件

pinia-plugin-persistedstate:pinia-plugin-persistedstate - npm (npmjs.com)

使用:
main.ts
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
const pinia = createPinia();
pinia.use(piniaPluginPersistedstate)
app.use(pinia)


具体的stores.ts文件
方法一:
直接设置 `persist: true` 即可
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'

export const userStore = defineStore('user', () => {
  const nick = ref('小明');
  const codes = ref(58);

  const msg = computed(() => {
    return '昵称:' + nick.value + ', 得分:' + codes.value
  })
  const moreMsg = computed(() => {
    return msg.value + ' | ' + (codes.value >= 60 ? '合格' : '不合格')
  })

  function renderCode() {
    codes.value = Math.floor(Math.random() * 100)
  }
  return { nick, codes, msg, moreMsg, renderCode }
}, {
  persist: true
})

方法二:
具体设置
import { defineStore } from 'pinia'

export const useStore = defineStore('store',() => {
  const nick = ref('小明');
  const codes = ref(58);
  return { nick, codes }
}, {
     persist: {
        storage: sessionStorage, // 设置存储位置,sessionStorage浏览器关闭就会清空,默认是localStorage
        paths: ['someState'],  // 需要持久话存储的数据
     },
})

你可能感兴趣的:(前端,javascript,开发语言)