Pinia简单上手

1. 概念
Pinia是Vue的储存库,允许跨组件/页面共享状态
2. 特性
  • 直观,像定义components一样定义 store
  • 完整的TypeScript支持
  • 去除了mutations,只有 state,getters,actions
  • actions支持同步和异步
  • Vue Devtools支持Pinia,提供更好的开发体验
  • 能够构建多个stores,并实现自动地代码拆分
  • 极其轻量(1kb),甚至感觉不到它的存在
3. 与Vuex比较
  • mutations不在存在
  • 无需创建自定义复杂包装器来支持TypeScript,所有内容都是类型化的,并且API的设计方式尽可能利用TS类型判断
  • 不再需要注入、导入函数、调用函数、享受自动完成功能
  • 无需动态添加Store,默认情况下它们都是动态的
  • 不再有mutations的嵌套结构
  • 没有命名空间模块
4. 基本使用
(1)安装
yarn add pinia
# 或者使用 npm
npm install pinia
(2)在main.js 中挂载pinia
import { createApp } from 'vue';
import App from './App.vue';
// 创建pinia
import { createPinia } from 'pinia';
const pinia = createPinia();
const app = createApp(App);
app.use(pinia).mount('#app')
(3)新建文件 store/index.js,定义一个Store
import { defineStore } from 'pinia'
// useStore 也可以是 useUser useXxxxStore 之类的任何东西
// 第一个参数是应用程序中 store的唯一id
// 第二个参数为一个对象,提供 state getters actions
const useStore = defineStore('main', {
	state:() => {
		return {
			count: 1
		}
	},
	getters: {},
	actions: {}
})

export default useStore

这个name,也称为id,是必要的,Pinia使用它来将store连接到 devtools。将返回的函数命名为 use… 是跨可组合项的约定,以使其符合你的使用习惯

(4)在组件中使用
<template>
	<h1>{{ store.count }}</h1>
</template>

<script>
import { defineComponent } from "vue";
import { useStore } from '@/stores/index'
export default defineComponent({
	setup() {
		const store = useStore()
		return {
			store 
		}
	}
})
</script>

注意:如果想要解构store赋值是不可行的,因为它会破坏响应式

setup() {
    const store = useStore()
    // ❌ 这不起作用,因为它会破坏响应式
    const { count } = store
    
    return {
      count, // 一直会是 1
      // 这将是响应式的
      count: computed(() => store.count),
      }
},

为了从 store中提取属性的同时保持其想应收,需要用到 storeToRefs()。它将为任何响应式属性创建refs。

import { storeToRefs } from "pinia";
setup(){
	const store = useStore()
	const { count } = storeToRefs(store)
	return {
		count
	}
}
5. getters

getters 完全等同于 store 状态的计算值

export const useStore = defineStore('main', {
  state: () => {
      return {
          count: 1,
      }
  },
  getters: {
    // 自动将返回类型推断为数字
    doubleCount(state) {
      return state.count* 2
    },
    // 设置了返回类型
    doublePlusOne(): number {
      return this.count* 2 + 1
    },
  },
})

// 在组件中使用
<template>
  <p>Double count is {{ store.count }}</p>
  <p>DoublePlusOne count is {{ store.count }}</p>
</template>

<script>
  setup() {
    const store = useStore()

    return { 
    	store 
    }
  }
</script>

getters 只是幕后的 computed 属性,因此无法向它们传递任何参数。但是,你可以从 getters 返回一个函数接收任何参数

export const useStore = defineStore('main', {
  getters: {
    getUserById: (state) => {
      return (userId) => state.users.find((user) => user.id === userId)
    },
  },
})

// 在组件中使用
<script>
export default {
  setup() {
    const store = useStore()

    return { 
    	getUserById: store.getUserById 
    }
  },
}
</script>

<template>
  <p>User 2: {{ getUserById(2) }}</p>
</template>

访问其他 store 的 getter

import { useOtherStore } from './other-store'

export const useStore = defineStore('main', {
  state: () => {
    return {
        localData: ...
    }
  },
  getters: {
    otherGetter(state) {
      const otherStore = useOtherStore()
      return state.localData + otherStore.data
    },
  },
})
6. actions

不管是同步还是异步的代码,都可以在 actions 中完成。actions 相当于组件中的 methods

export const useStore = defineStore('main', {
  state: () => ({
    count: 0,
  }),
  actions: {
    increment() {
      this.count++
    },
    randomizeCount() {
      this.count = Math.round(100 * Math.random())
    },
    incrementAsync() {
		setTimeout(() => {
        	this.count++
      	}, 1000)
	}
  },
})

在组件中使用

<h1>数量---{{ store.count }}</h1>
<button @click="store.increment">1</button>
<button @click="store.randomizeCount">随机</button>
<button @click="store.incrementAsync">异步加1</button>

setup() {
    const store = useStore()

    return { 
    	store
    }
},
7. pinia模块化

在项目中,不可能把多个模块的数据放在一个store中,一般都是一个模块对应一个store,再通过一个跟store进行整合

// 新建store/user.js
import { defineStore } from 'pinia'
 
const useUserStore = defineStore('user', {
  state: () => {
    return {
      name: 'zs',
      age: 18,
    }
  },
})
export default useUserStore
//新建store/app.js
import { defineStore } from 'pinia'
 
const useAppStore = defineStore('app', {
  state: () => {
    return {
		roles: []
    }
  },
})
export default useAppStore
// 在store/index.js 中
import useUserStore from './user'
import useAppStorefrom './app'

// 统一导出useStore方法
export default function useStore() {
  return {
    user: useUserStore(),
    counter: useAppStorefrom (),
  }
}
// 在组件中使用
<script>
import useStore from "@/store/index";

setup() {
	const { app, user } = useStore();
	
	const { name, age } = storeToRefs(user)
}
</script>
8. pinia 数据持久化
(1)安装
yarn add pinia-plugin-persistedstate
or
npm i  pinia-plugin-persistedstate
(2)在main.js中注册
import { createApp } from 'vue';
import App from './App.vue';
// 创建pinia
import { createPinia } from 'pinia';
// 引入 pinia插件-数据持久化
import PiniaPluginPersistedstate from 'pinia-plugin-persistedstate';

const pinia = createPinia();
pinia.use(PiniaPluginPersistedstate)
const app = createApp(App);
app.use(pinia).mount('#app');
(3)使用
import { defineStore } from 'pinia'

export const useStore = defineStore('store', {
  state: () => {
    return {
      someState: 'hello pinia',
    }
  },
  persist: true,
})
(4)配置储存持久化的方式,为presist属性指定选项
import { defineStore } from 'pinia'

export const useStore = defineStore('store', {
  state: () => {
    return {
      someState: 'hello pinia',
    }
  },
  persist: {
  	key: 'someState', // 作为存储的默认秘钥,存储中的键名称
    storage: sessionStorage, // 默认为localStorage
    paths: ['someState'], // 部分保持状态的点符号路径数组。[]意味着没有状态被持久化,undefined或者null意味着整个状态被持久化
  },
})
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值