Pinia는 Vue에서 개발한 새로운 상태 관리 라이브러리인데, 초보자가 Pinia를 시작하려면 어떻게 해야 하나요? 다음 글에서는 Pinia를 소개하고 핵심 기능과 간단한 사용법을 소개하겠습니다.
Vuex는 모두에게 친숙한 오래된 Vue 상태 관리 라이브러리입니다.
Pinia는 Vue.js 팀 구성원이 Vue용으로 특별히 개발한 새로운 상태 관리 라이브러리이며 공식 github에 포함되었습니다.
Vuex가 이미 있는데 왜 Pinia를 개발해야 하나요?
차세대 Vuex5가 어떤 모습이어야 할지 Vuex5에 대한 제안을 먼저 사진으로 살펴보겠습니다. [관련 추천 : vuejs 영상 튜토리얼]
Pinia는 당시 Vuex5 제안에서 언급한 기능적 사항을 완벽하게 준수하고 있어서 Pinia가 공식 개발자이기 때문에 Vuex5라고 해도 과언이 아닙니다. , 공식적으로 인수되었지만 현재 Vuex와 Pinia는 여전히 두 개의 독립적인 웨어하우스입니다. 향후 독립적으로 병합되거나 개발될 수 있지만 Vue3에서 Vuex를 사용해야 하기 때문에 공식적인 권장 사항은 Pinia
입니다. 과도기적 선택으로 사용되었으며 큰 결함이 있습니다. 따라서 Componsition API가 탄생한 후 새로운 상태 관리 Pinia
Vuex가 설계되었습니다: State
, Gettes
, Mutations
(동기), Actions
(비동기)State
、Gettes
、Mutations
(同步)、Actions
(异步)
Pinia: State
、Gettes
、Actions
(同步异步都支持)
Vuex 当前最新版是 4.x
Pinia 当前最新版是 2.x
就目前而言 Pinia 比 Vuex 好太多了,解决了 Vuex 的很多问题,所以笔者也非常建议直接使用 Pinia,尤其是 TypeScript 的项目
Mutations
Actions
支持同步和异步TypeScript
支持Vue DevTools
以 Vue3 + TypeScript
为例
安装
npm install pinia
main.ts
初始化配置
import { createPinia } from 'pinia'createApp(App).use(createPinia()).mount('#app')
在 store 目录下创建一个 user.ts
为例,我们先定义并导出一个名为 user
的模块
import { defineStore } from 'pinia' export const userStore = defineStore('user', { state: () => { return { count: 1, arr: [] } }, getters: { ... }, actions: { ... } })
defineStore
Pinia
: State
, Gettes code>, Actions
(동기식 및 비동기식 모두 지원)
4.x
🎜2.x
🎜돌연변이
가 없습니다Actions
는 동기식 및 비동기식을 지원합니다TypeScript
지원 Vue DevTools
Vue3 + TypeScript
를 예로 사용합니다🎜🎜installation🎜<template> <div>{{ user_store.count }}</div> </template> <script setup> import { userStore } from '../store' const user_store = userStore() // 解构 // const { count } = userStore() </script>🎜
main.ts
초기화 구성🎜<template> <div>{{ count }}</div> </template> <script setup> import { storeToRefs } from 'pinia' import { userStore } from '../store' const { count } = storeToRefs(userStore) </script>🎜in store 디렉토리에
user.ts
를 생성합니다. 예를 들어 먼저 user
라는 모듈을 정의하고 내보냅니다. 🎜<template> <div>{{ myCount }}</div> <div>{{ myCount }}</div> <div>{{ myCount }}</div> </template>🎜
defineStore
는 수신합니다. 두 개의 매개변수 🎜🎜첫 번째 매개변수는 모듈의 이름이며, 여러 모듈이 동일한 이름을 가질 수 없습니다. Pinia는 모든 모듈을 루트 컨테이너에 마운트합니다. Vuex Almost🎜와 동일state
用来存储全局状态,它必须是箭头函数,为了在服务端渲染的时候避免交叉请求导致的数据状态污染所以只能是函数,而必须用箭头函数则为了更好的 TS 类型推导getters
就是用来封装计算属性,它有缓存的功能actions
就是用来封装业务逻辑,修改 state比如我们要在页面中访问 state 里的属性 count
由于 defineStore
会返回一个函数,所以要先调用拿到数据对象,然后就可以在模板中直接使用了
<template> <div>{{ user_store.count }}</div> </template> <script setup> import { userStore } from '../store' const user_store = userStore() // 解构 // const { count } = userStore() </script>
比如像注释中的解构出来使用,是完全没有问题的,只是注意了,这样拿到的数据不是响应式的,如果要解构还保持响应式就要用到一个方法 storeToRefs()
,示例如下
<template> <div>{{ count }}</div> </template> <script setup> import { storeToRefs } from 'pinia' import { userStore } from '../store' const { count } = storeToRefs(userStore) </script>
原因就是 Pinia 其实是把 state 数据都做了 reactive
处理,和 Vue3 的 reactive 同理,解构出来的也不是响应式,所以需要再做 ref
响应式代理
这个和 Vuex 的 getters 一样,也有缓存功能。如下在页面中多次使用,第一次会调用 getters,数据没有改变的情况下之后会读取缓存
<template> <div>{{ myCount }}</div> <div>{{ myCount }}</div> <div>{{ myCount }}</div> </template>
注意两种方法的区别,写在注释里了
getters: { // 方法一,接收一个可选参数 state myCount(state){ console.log('调用了') // 页面中使用了三次,这里只会执行一次,然后缓存起来了 return state.count + 1 }, // 方法二,不传参数,使用 this // 但是必须指定函数返回值的类型,否则类型推导不出来 myCount(): number{ return this.count + 1 } }
更新 state 里的数据有四种方法,我们先看三种简单的更新,说明都写在注释里了
<template> <div>{{ user_store.count }}</div> <button @click="handleClick">按钮</button> </template> <script setup> import { userStore } from '../store' const user_store = userStore() const handleClick = () => { // 方法一 user_store.count++ // 方法二,需要修改多个数据,建议用 $patch 批量更新,传入一个对象 user_store.$patch({ count: user_store.count1++, // arr: user_store.arr.push(1) // 错误 arr: [ ...user_store.arr, 1 ] // 可以,但是还得把整个数组都拿出来解构,就没必要 }) // 使用 $patch 性能更优,因为多个数据更新只会更新一次视图 // 方法三,还是$patch,传入函数,第一个参数就是 state user_store.$patch( state => { state.count++ state.arr.push(1) }) } </script>
第四种方法就是当逻辑比较多或者请求的时候,我们就可以封装到示例中 store/user.ts 里的 actions 里
可以传参数,也可以通过 this.xx 可以直接获取到 state 里的数据,需要注意的是不能用箭头函数定义 actions,不然就会绑定外部的 this 了
actions: { changeState(num: number){ // 不能用箭头函数 this.count += num } }
调用
const handleClick = () => { user_store.changeState(1) }
打开开发者工具的 Vue Devtools
就会发现 Pinia,而且可以手动修改数据调试,非常方便
示例:
我们先定义示例接口 api/user.ts
// 接口数据类型 export interface userListType{ id: number name: string age: number } // 模拟请求接口返回的数据 const userList = [ { id: 1, name: '张三', age: 18 }, { id: 2, name: '李四', age: 19 }, ] // 封装模拟异步效果的定时器 async function wait(delay: number){ return new Promise((resolve) => setTimeout(resolve, delay)) } // 接口 export const getUserList = async () => { await wait(100) // 延迟100毫秒返回 return userList }
然后在 store/user.ts 里的 actions 封装调用接口
import { defineStore } from 'pinia' import { getUserList, userListType } from '../api/user' export const userStore = defineStore('user', { state: () => { return { // 用户列表 list: [] as userListType // 类型转换成 userListType } }, actions: { async loadUserList(){ const list = await getUserList() this.list = list } } })
页面中调用 actions 发起请求
<template> <ul> <li v-for="item in user_store.list"> ... </li> </ul> </template> <script setup> import { userStore } from '../store' const user_store = userStore() user_store.loadUserList() // 加载所有数据 </script>
在一个模块的 actions 里需要修改另一个模块的 state 数据
示例:比如在 chat 模块里修改 user 模块里某个用户的名称
// chat.ts import { defineStore } from 'pinia' import { userStore } from './user' export const chatStore = defineStore('chat', { actions: { someMethod(userItem){ userItem.name = '新的名字' const user_store = userStore() user_store.updateUserName(userItem) } } })
user 模块里
// user.ts import { defineStore } from 'pinia' export const userStore = defineStore('user', { state: () => { return { list: [] } }, actions: { updateUserName(userItem){ const user = this.list.find(item => item.id === userItem.id) if(user){ user.name = userItem.name } } } })
위 내용은 Vue의 새로운 상태 관리 Pinia를 시작하는 방법은 이 기사를 읽어보세요!의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!