惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Simon Willison's Weblog
Simon Willison's Weblog
Google DeepMind News
Google DeepMind News
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
P
Proofpoint News Feed
Recent Announcements
Recent Announcements
MongoDB | Blog
MongoDB | Blog
U
Unit 42
云风的 BLOG
云风的 BLOG
Recorded Future
Recorded Future
G
Google Developers Blog
I
InfoQ
Blog — PlanetScale
Blog — PlanetScale
A
About on SuperTechFans
Jina AI
Jina AI
量子位
宝玉的分享
宝玉的分享
The Cloudflare Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - 聂微东
Last Week in AI
Last Week in AI
WordPress大学
WordPress大学
美团技术团队
The Hacker News
The Hacker News
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
Tailwind CSS Blog
博客园 - 司徒正美
博客园 - 叶小钗
Hugging Face - Blog
Hugging Face - Blog
P
Palo Alto Networks Blog
博客园_首页
阮一峰的网络日志
阮一峰的网络日志
博客园 - 【当耐特】
Spread Privacy
Spread Privacy
The GitHub Blog
The GitHub Blog
Y
Y Combinator Blog
Vercel News
Vercel News
Martin Fowler
Martin Fowler
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Forbes - Security
Forbes - Security
Attack and Defense Labs
Attack and Defense Labs
Google DeepMind News
Google DeepMind News
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Microsoft Azure Blog
Microsoft Azure Blog
P
Privacy International News Feed
G
GRAHAM CLULEY
The Last Watchdog
The Last Watchdog
C
Cyber Attacks, Cyber Crime and Cyber Security
AI
AI
V2EX - 技术
V2EX - 技术

Mengke's blog - Mengke's coding journey

年轻不是健康的免死金牌 深圳工作机会,前端 2025 年终总结 Skill 不是 MCP 的替代品:我理解的渐进式披露与选型原则 独立开发者如何开具发票 香港银行卡开户完整指南(2025年9月最新) 招商银行储蓄卡微信动账提醒恢复方法 再谈 MCP - Model Context Protocol(MCP)详解和开发教程 Get Human-Readable "Time Ago" in TypeScript 以「asset-price-mcp」为例,从 0 开发 MCP Server Model Context Protocol (MCP) 快速开始 DeepSeek + Dify 搭建本地知识库 An elegant solution for implementing optional property types using TypeScript 2024 年终总结 Quickly Create a Fullscreen WebView with Autoplay Support for Testing 以数字开头的 ID 在 querySelector 中的处理 String casing utilities in JavaScript Check if a string is a valid color Simple Event-Emitter/PubSub pattern Find which process is running on a certain port and kill it Markdown Code block's basic and advanced syntaxes Common npm commands to use locally Pnpm aliases How to safely rename a case sensitive file/directory in a git repo? A custom hooks to use an async effect A custom hooks to use local storage state 🤩 Mengke'blog 上线的这一年 🗼 五月底去了一趟日本,记录一下我的游记和攻略 网站性能优化:如何高效预加载大型静态资源 闰年之约 - 2024年2月29日 A collection of some useful websites 2023 年终总结 WebGL 学习笔记(一)基础概念与实践 Android Webview <video> 标签去除默认播放按钮图 📷 纯前端也可以实现「用户无感知录屏」? Getting Spotify token to display now playing track on your website AVP - Web 端特效视频播放器 IndexedDB 基础入门 直接下载网易云音乐中歌曲MP3格式的方法 什么!一个项目给了8个字体包??? flex 布局中 start/end 和 flex-start/flex-end 的区别 深入 Pinia:从代码出发探索 Vue 状态管理的奥秘 Nest.js Typrorm 多对多关系如何创建 Strapi 快速入门 CentOS7 MySQL 数据库安装与卸载 Next.js 上手指南 Vue 数据响应式原理 deno 快速上手 - Hello World 案例 快速上手 Vue3 尝鲜 Vue 3.0 Combination API react-router-dom 路由基础教程 JavaScript 数组扁平化处理的方法总结
Pinia 快速上手指南
Mengke · 2023-04-12 · via Mengke's blog - Mengke's coding journey

Server.webp

Published on
/

6 mins read

/

––– views

Share:

优势

  • vue 2、3 都支持。
  • 抛弃传统的 Mutation ,只有 stategetteraction ,简化了代码结构。
  • 不需要嵌套模块,符合 Composition API 代码风格。
  • 支持 TS。
  • 代码简洁。

安装

初始化项目: npm init vite@latest

安装 Pinia : npm i pinia

创建 Store

// src/store/index.ts
 
import { createPinia } from 'pinia'
 
const store = createPinia()
export default store

在 main.ts 中引入并使用:

// src/main.ts
 
import { createApp } from 'vue'
import App from './App.vue'
import store from './store'
 
const app = createApp(App)
app.use(store)

State

定义 state:

import { defineStore } from 'pinia'
 
export const useMainStore = defineStore('mainStore', {
  state: () => ({
    msg: 'Hello World!',
  }),
  getters: {},
  actions: {},
})

获取 state:

<template>
  <div>{{ store.msg }}</div>
</template>
<script lang="ts" setup>
  import { useMainStore } from '../../store'
  const store = useMainStore()
</script>

也可以结合 computed

const msg = computed(() => store.msg)

解构 state

需要同时获取 Store 中的多个值时,通常会使用解构赋值的方式。但在 Pinia 中直接解构会造成数据失去响应性:

<template>
    <div>{{ msg }}--{{ store.msg }}</div>
</template>
<script lang="ts" setup>
	import { useMainStore } from '../../store';
	const store = useMainStore();
	const { msg } = store;
	setTimeout(() => {
	    console.log("patch");
	    store.$patch({ msg: 'change' });
	}, 2000);
</script

Untitled

storeToRefs 结构方法:

import { storeToRefs } from 'pinia'
const { msg } = storeToRefs(store)

Untitled

修改 state

直接通过 store.属性名 来修改。

store.count = 100

多条数据修改:

  • 「不建议」多条数据的修改也可以直接通过 store.属性名 来修改:

    const change = () => {
      store.obj = { a: 8, b: 7, c: 9 }
    }
  • 使用 $patch来修改数据:

    // $patch 对象
    store.$patch({
      count: store.count + 2,
      msg: 'This is Pinia World',
    })
     
    // or
     
    // $patch 函数
    store.$patch((state) => {
      state.arrs.push({ name: 'haha', age: 12 })
      state.hasChange = true
    })
  • 通过 action 修改:

    export const useMainStore = defineStore('mainStore', {
      state: () => ({
        msg: 'Hello World!',
      }),
      getters: {},
      actions: {
        changeMsg(newMsg) {
          this.msg = newMsg
        },
      },
    })
     
    const store = useMainStore()
    store.changeMsg('哈哈哈')

Getters

等同于 store 的 state 的 计算值 。可以这样定义:

export const useMainStore = defineStore("mainStore", {
    state: () => ({
        msg: "Hello World!",
				users: [
            { id: 1, name: "aa" },
            { id: 2, name: "bb" },
            { id: 3, name: "cc" }
        ]
    }),
    getters: {
        myMsg(state) {
            return `${state.msg} === 111`;
        },
				// 访问其他 getter
        myMsg2(state): string {
            return `${this.getMsg} === 222`;
        },
				// 向 getter 传递参数
				getUserById: (state) => {
		      return (userId) => state.users.find((user) => user.id === userId)
		    },
    }
});
 
const store = useMainStore();
console.log(store.myMsg1);    // Hello World! === 111
console.log(store.myMsg2);    // Hello World! === 111 === 222
console.log(store.getUserById(2));    // { id: 2, name: "bb" }

getter 中传递参数的方法会让 getter 不再被缓存 ,不过我们可以手动做一下缓存:

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

访问其他 store

export const useStore1 = defineStore('store1', () => {
  const store1Count = ref(2)
  return { store1Count }
})
export const useStore2 = defineStore('store2', {
  state: () => ({
    store2Count: 100,
  }),
  getters: {
    countTotal(state) {
      return useStore1().store1Count + state.store2Count
    },
  },
})
 
const store2 = useStore2()
console.log(store.countTotal) // 102

Actions

异步 action

export const useStore = defineStore('store', {
  actions: {
    async getData() {
      const response = await fetch('https://getman.cn/echo')
      const data = await response.text()
      return data
    },
  },
})
const store = useStore()
const data = await store.getData()
console.log(data)

action 相互调用

export const useUserStore = defineStore('store', {
  actions: {
    async login(account, pwd) {
      const { data } = await api.login(account, pwd)
      this.setData(data) // 调用另一个 action 的方法
      return data
    },
    setData(data) {
      console.log(data)
    },
  },
})

action 调用其他 store 的 action

同 getter;访问其他 store

数据持久化

插件 pinia-plugin-persist 可以辅助实现数据持久化功能。

安装

npm i pinia-plugin-persist --save

使用

// src/store/index.ts
 
import { createPinia } from 'pinia'
import piniaPluginPersist from 'pinia-plugin-persist'
 
const store = createPinia()
store.use(piniaPluginPersist)
 
export default store

接着在对应的 store 里开启 persist 即可。

export const useUserStore = defineStore('user', {
  state: () => ({
    name: '张三',
  }),
  // 开启数据缓存
  persist: {
    enabled: true,
  },
})

https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1dc6800f21674e3cbcc1fc02af4c7051~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp?

数据默认存在 sessionStorage 里,并且会以 store 的 id 作为 key。

自定义 key

你也可以在 strategies 里自定义 key 值,并将存放位置由 sessionStorage 改为 localStorage

persist: {
		enabled: true,
	  strategies: [
		    {
			      key: 'my_user',
			      storage: localStorage,
		    }
	  ]
}

https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/42ebf8aa98394052ad8fd5e4afb3ca3f~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp?

持久化部分 state

默认所有 state 都会进行缓存,你可以通过 paths 指定要持久化的字段,其他的则不会进行持久化。

state: () => ({
		name: "张三",
    age: 18,
    gender: "男"
}),
persist: {
    enabled: true,
    strategies: [
        {
            storage: localStorage,
            paths: ["name", "age"]
        }
    ]
}

上面我们只持久化 nameage,并将其改为 localStorage, 而 gender 不会被持久化,如果其状态发生更改,页面刷新时将会丢失,重新回到初始状态,而 nameage 则不会。


附:Pinia 速查表

1. 安装 Pinia

Untitled

2. 定义 store

Untitled

3. 使用 store (组合式 API)

Untitled

4. 使用 store (选项式 API)

Untitled

5. 修改 state

Untitled

6. 订阅修改

Untitled

Back to posts

On this page
  • 优势
  • 安装
  • 创建 Store
  • State
  • 定义 state:
  • 获取 state:
  • 解构 state
  • 修改 state
  • 多条数据修改:
  • Getters
  • 访问其他 store
  • Actions
  • 异步 action
  • action 相互调用
  • action 调用其他 store 的 action
  • 数据持久化
  • 安装
  • 使用
  • 自定义 key
  • 持久化部分 state
  • 附:Pinia 速查表
  • 1. 安装 Pinia
  • 2. 定义 store
  • 3. 使用 store (组合式 API)
  • 4. 使用 store (选项式 API)
  • 5. 修改 state
  • 6. 订阅修改