Vue3에서 Pinia 사용에 대한 자세한 설명

소개

Pinia는 Vue.js를 위해 특별히 설계된 상태 관리 라이브러리로, 애플리케이션 상태를 관리하는 쉽고 직관적인 방법을 제공합니다. Pinia를 사용하면 상태를 정의하는 저장소를 만든 다음 Vue 구성 요소와 바인딩하여 해당 상태를 사용할 수 있도록 하는 것이 쉽습니다. 이전 블로그에서 언급한 Vuex와 비교할 때 Pinia는 사용하기 쉽고 크기가 작으며 TypeScript 지원 및 플러그인 시스템이 더 좋습니다.

Vue.js의 공식 웹사이트에서 Pinia가 Vuex를 대체하고 Vue 생태계의 일부가 된 것을 볼 수 있습니다.

Pinia 설치 및 구성

Pinia 설치 및 구성은 매우 간단합니다. 다른 Vue 플러그인과 마찬가지로 Pinia는 yarn 또는 npm을 통해 설치하고 Vue 애플리케이션과 함께 번들로 제공해야 합니다. 다음 명령을 사용하여 설치할 수 있습니다.

yarn add pinia
# 或者使用 npm
npm install pinia

Pinia 패키지를 설치한 후 다음과 같이 main.ts 파일에서 createPinia 함수를 가져오고 Pinia 플러그인을 Vue 애플리케이션과 바인딩해야 합니다.

import {
    
     createApp } from 'vue';
import {
    
     createPinia } from 'pinia';
import App from './App.vue';

const app = createApp(App);

const pinia = createPinia();
app.use(pinia);

app.mount('#app');

createPinia() 함수를 사용하여 Pinia 플러그인 인스턴스를 생성 및 초기화하고 app.use(pinia)를 사용하여 Vue 애플리케이션에 바인딩합니다. 이 시점에서 Pinia를 사용하여 Vue 애플리케이션의 상태를 관리할 수 있습니다.

피니아의 핵

가게

Store는 Pinia에서 상태를 관리하는 핵심 개념입니다. Vue 구성 요소의 상태와 동일하지만 Store는 별도의 모듈입니다.

저장소는 defineStore()로 정의되며 첫 번째 매개변수에는 고유한 이름이 필요합니다. 이 이름은 id로도 사용되며 전달되어야 합니다. Pinia는 이 이름을 사용하여 저장소와 devtools를 연결합니다. 습관적인 사용법을 개발하기 위해 반환된 함수의 이름을 use...로 지정하는 것은 구성 함수 스타일을 준수하는 규칙입니다.

defineStore()의 두 번째 매개변수는 두 가지 유형의 값, 즉 Setup 함수 또는 Option 개체를 허용할 수 있습니다.

Store를 정의하는 예제 코드:

import {
    
     defineStore } from 'pinia'

// 你可以对 `defineStore()` 的返回值进行任意命名,但最好使用 store 的名字,同时以 `use` 开头且以 `Store` 结尾。(比如 `useUserStore``useCartStore``useProductStore`)
// 第一个参数是你的应用中 Store 的唯一 ID。
export const useAlertsStore = defineStore('alerts', {
    
    
  // 其他配置...
})

상태

상태는 저장소에 데이터가 저장되는 위치입니다. 상태를 정의하면 저장소 어디에서나 데이터에 액세스하고 수정할 수 있습니다.

Pinia에서 상태는 초기 상태를 반환하는 함수로 정의됩니다. 이를 통해 Pinia는 서버와 클라이언트를 모두 지원할 수 있습니다.
State를 정의하는 샘플 코드는 다음과 같습니다.

import {
    
     defineStore } from 'pinia'

const useStore = defineStore('storeId', {
    
    
  // 为了完整类型推理,推荐使用箭头函数
  state: () => {
    
    
    return {
    
    
      // 所有这些属性都将自动推断出它们的类型
      count: 0,
      name: 'Eduardo',
      isAdmin: true,
      items: [],
      hasChanged: true,
    }
  },
})

얻는 사람

Getter는 Vue 구성 요소의 계산된 속성과 유사하게 상태에서 파생된 데이터를 가져오는 데 사용됩니다. defineStore()의 getters 속성을 통해 정의할 수 있습니다. 화살표 함수가 권장되며 상태를 첫 번째 인수로 받습니다.

export const useStore = defineStore('main', {
    
    
  state: () => ({
    
    
    count: 0,
  }),
  getters: {
    
    
    doubleCount: (state) => state.count * 2,
  },
})

행동

작업은 구성 요소의 메서드와 동일합니다. defineStore()의 actions 속성을 통해 정의할 수 있으며, Action은 스토어에서 비동기 작업을 캡슐화하는 방법으로 호출할 수 있는 함수이며 스토어에서 매개변수를 수신하고 상태를 수정할 수도 있습니다. 작업은 항상 동기적이어야 하며 비동기 작업을 처리할 때 결과가 잘 처리되도록 Promise를 반환해야 합니다.

Pinia의 Action은 defineStore에 의해 생성되며 action에서 정의하여 사용할 수 있습니다. 예를 들어 다음은 매장의 작업 정의입니다.

import {
    
     defineStore } from 'pinia'

export const myStore = defineStore('myStore',{
    
     
  state: () => ({
    
    
    message: 'Hello',
  }),
  actions: {
    
    
    async fetchMessage() {
    
    
      const response = await fetch('http://127.0.0.1:5173/message')
      const data = await response.json()
      this.message = data.message
    },
  },
})

위의 예에서는 백그라운드 API에서 데이터를 가져오고 스토어의 상태를 업데이트하는 myStore, fetchMessage()에 대한 작업을 정의합니다. 그런 다음 구성 요소 또는 다른 작업에서 이 작업을 호출할 수 있습니다.

import {
    
     useStore } from 'pinia'

export default {
    
    
  setup() {
    
    
    const store = useStore('myStore')

    function handleClick() {
    
    
      store.fetchMessage()
    }

    return {
    
    
      handleClick,
    }
  },
}

위의 코드에서 구성 요소의 useStore 후크를 사용하여 저장소 인스턴스를 가져온 다음 이를 fetchMessage() 메서드에 전달합니다. 이 메서드는 앱의 백그라운드에서 데이터를 가져오고 메모리의 상태를 업데이트합니다. 마지막으로 handleClick() 메서드가 노출되어 구성 요소가 이 메서드를 호출하고 액션을 트리거할 수 있습니다.

Pinia 생성 및 사용

피니아 만들기

이전에 Pinia를 설치하고 구성한 적이 있습니다.Pinia를 생성하기 전에 코드의 통합 관리 및 유지 보수를 위해 여전히 저장소 폴더를 먼저 생성한 다음 관련 Pinia를 생성합니다.구체적인 단계는 다음과 같습니다.

  1. src 폴더 아래에 새로운 store 폴더를 생성하고 상태 관리를 위해 Pinia를 필요로 하는 모든 후속 코드는 이 폴더에 배치됩니다.
  2. store 폴더 아래에 새로운 movieListStore.js 파일을 생성하고 생성이 완료되면 파일 열기
  3. movieListStore.js 파일에서 Pinia의 defineStore 메소드를 소개합니다.
import {
    
     defineStore } from 'pinia'
  1. defineStore 객체를 생성하고, defineStore에서 생성한 객체를 받을 useMovieListStore를 정의하고, export default를 통해 내보냅니다.
 const useMovieListStore = defineStore('movie',{
    
     
  state: () => ({
    
    
    isShow: true,
    movies: [],
  }),
  getters: {
    
    
    getIsShow() {
    
    
      return this.isShow
    },
    getMovies() {
    
    
      return this.movies
    },
  },
  actions: {
    
    
    setIsShow(value) {
    
    
      this.isShow = value
    },
    async fetchMovies() {
    
    
      const response = await fetch('https://api.movies.com/movies')
      const data = await response.json()
      this.movies = data
    },
  },
})
export default useMovieListStore 

위의 코드에서 우리는 action을 사용하여 동기 메서드 setIsShow와
비동기 메서드 fetchMovies의 두 가지 메서드를 정의합니다
. 참고:
여기서 공식적인 제안은 후크 함수를 정의할 때 이름 지정 메서드를 사용하는 것이 좋습니다. 사용 시작 시점과 Store 종료 시점 위의 useMovieListStore와 같이 위에서 생성한 개체의 이름을 지정합니다.

피니아 사용

이전에 Pinia를 만든 다음 구성 요소에서 사용할 수 있습니다.
Vue 컴포넌트에서 스토어를 사용하려면 useStore() 함수를 통해 스토어 인스턴스에 액세스해야 합니다.
Vue 컴포넌트에서 Pinia를 사용하는 단계는 다음과 같습니다.

  1. 먼저 가져오기를 사용하여 Pinia에 useStore를 도입합니다.
import {
    
     useStore } from 'pinia'
  1. useStore 객체 생성
const store = useStore('movie')
  1. 상태를 가져와야 하는 곳에서 위에서 정의한 store.getIsShow()를 통해 상태를 가져옵니다.
return {
    
    
   isShow: store.getIsShow(),
}

Menu.vue의 전체 샘플 코드는 다음과 같습니다.

<template>
  <nav>
    <ul>
      <li v-show="isShow">{
    
    {
    
     $route.name }} </li>
      <li><router-link to="/">Home</router-link></li>
      <li><router-link to="/movies">Movies</router-link></li>
    </ul>
  </nav>
</template>

<script>
import {
    
     defineComponent } from 'vue'
import {
    
     useStore } from 'pinia'

export default defineComponent({
    
    
  name: 'Menu',

  setup() {
    
    
    const store = useStore('movie')

    return {
    
    
      isShow: store.getIsShow(),
    }
  },
})
</script>

Pinia의 Option Store 방식은 Store를 정의합니다.

Store를 정의하는 Option Store 방식은 Vue의 옵션 API와 유사하며, state, actions, getters 속성을 가진 Option 객체를 전달하여 정의합니다. 샘플 코드는 다음과 같습니다.

export const useCounterStore = defineStore('counter', {
    
    
  state: () => ({
    
     count: 0 }),
  getters: {
    
    
    double: (state) => state.count * 2,
  },
  actions: {
    
    
    increment() {
    
    
      this.count++
    },
  },
})

상태를 저장소의 데이터(data)로, getter를 저장소의 계산된 속성(computed)으로, 작업을 메서드(methods)로 생각할 수 있습니다.

Pinia의 Setup Store 방식은 Store를 정의합니다.

Setup Store는 Option Store와 약간 다르며, Vue 컴포지트 API의 설정 기능과 유사합니다. 일부 응답 속성 및 메서드를 정의하는 함수를 전달하고 노출하려는 속성 및 메서드가 포함된 함수를 반환합니다. .메서드 객체. 샘플 코드는 다음과 같습니다.

export const useCounterStore = defineStore('counter', () => {
    
    
  const count = ref(0)
  function increment() {
    
    
    count.value++
  }

  return {
    
     count, increment }
})

설정 스토어에서:

  • ref()는 상태 속성입니다.
  • computed()는 게터입니다.
  • function()은 액션입니다.

샘플 코드

다음은 Pinia 상태 관리의 사용을 완전히 설명하는 예입니다.이제 다음과 같은 효과를 달성해야 합니다:
페이지에서 두 가지 기능을 완료해야 합니다.한 가지 기능은 isShow 값을 모니터링하여 다른 페이지의 점프를 제어하는 ​​것입니다. . 버튼 표시 및 숨기기, 또 다른 기능은 영화 목록을 가져와 세부 정보 페이지에 표시하는 기능을 통해 네트워크에 연결하는 것입니다.

선택적 API에서 구현 코드는 다음과 같습니다.

  1. main.js의 코드
// main.js

import {
    
     createApp } from 'vue'
import App from './App.vue'
import {
    
     createPinia } from 'pinia'
import {
    
     movieStore } from './store/movieStore'

const app = createApp(App)

app.use(createPinia())
app.use(movieStore)

app.mount('#app')
  1. store 폴더 아래에 있는 movieStore.js의 코드
// store/movieStore.js

import {
    
     defineStore } from 'pinia'

export const useMovieListStore = defineStore('movie',{
    
     
  state: () => ({
    
    
    isShow: true,
    movies: [],
  }),
  getters: {
    
    
    getIsShow() {
    
    
      return this.isShow
    },
    getMovies() {
    
    
      return this.movies
    },
  },
  actions: {
    
    
    setIsShow(value) {
    
    
      this.isShow = value
    },
    async fetchMovies() {
    
    
      const response = await fetch('https://api.movies.com/movies')
      const data = await response.json()
      this.movies = data
    },
  },
})
  1. 구성 요소 폴더 아래에 있는 Menu.vue 파일의 코드
<!-- components/Menu.vue -->

<template>
  <nav>
    <ul>
      <li v-show="isShow">{
    
    {
    
     $route.name }} </li>
      <li><router-link to="/">Home</router-link></li>
      <li><router-link to="/movies">Movies</router-link></li>
    </ul>
  </nav>
</template>

<script>
import {
    
     defineComponent } from 'vue'
import {
    
     useStore } from 'pinia'

export default defineComponent({
    
    
  name: 'Menu',

  setup() {
    
    
    const store = useStore('movie')

    return {
    
    
      isShow: store.getIsShow(),
    }
  },
})
</script>
  1. 구성 요소 폴더 아래의 MovieList.vue 코드
<!-- components/MovieList.vue -->

<template>
  <ul>
    <li v-for="movie in movies" :key="movie.id">
      <router-link :to="`/movies/${
      
      movie.id}`">{
    
    {
    
     movie.title }}</router-link>
    </li>
  </ul>
</template>

<script>
import {
    
     defineComponent } from 'vue'
import {
    
     useStore } from 'pinia'

export default defineComponent({
    
    
  name: 'MovieList',

  setup() {
    
    
    const store = useStore('movie')

    store.fetchMovies()

    return {
    
    
      movies: store.getMovies(),
    }
  },
})
</script>
  1. views 폴더 아래의 MovieDetails.vue 코드
<!-- views/MovieDetails.vue -->

<template>
  <div v-if="movie">
    <h2>{
    
    {
    
     movie.title }}</h2>
    <p>{
    
    {
    
     movie.description }} </p>
  </div>
  <div v-else>
    <h2>Movie Not Found</h2>
  </div>
</template>

<script>
import {
    
     defineComponent } from 'vue'
import {
    
     useRoute } from 'vue-router'
import {
    
     useStore } from 'pinia'

export default defineComponent({
    
    
  name: 'MovieDetails',

  setup() {
    
    
    const route = useRoute()
    const store = useStore('movie')
    const movieId = route.params.id
    const movie = store.getMovies().find((movie) => movie.id === movieId)

    return {
    
    
      movie,
    }
  },
})
</script>

위의 코드는 Pinia에서 store, getter 및 action을 사용하여 상태를 공유하고 관리하는 방법을 보여줍니다. 그 중 movieStore는 isShow와 movies의 두 가지 상태를 담고 있는 store와 isShow를 수정하고 영화 목록을 얻기 위한 action을 정의한다. Menu.vue 구성 요소에서 useStore 후크를 사용하여 상점에서 isShow 상태를 가져오고 해당 값에 따라 하단 메뉴 막대 버튼의 표시 및 숨기기를 제어합니다. MovieList.vue 구성 요소에서 useStore 후크를 사용하여 스토어에서 영화 상태를 가져오고 fetchMovies() 작업을 사용하여 네트워크에서 영화 목록을 가져옵니다. MovieDetails.vue 구성 요소에서 useRoute 후크를 사용하여 현재 페이지의 라우팅 매개 변수 ID를 가져오고 useStore 후크를 사용하여 스토어에서 영화 상태를 가져오고 movieId에 따라 현재 영화의 세부 정보를 가져옵니다. getMovies() 게터.

setup() 후크에서 useStore 후크를 사용하여 상태를 가져오고 저장소에서 작업을 수행합니다. useStore 후크가 반응 프록시를 반환하므로 상태를 반응적으로 수동으로 업데이트할 필요가 없습니다. 또한 저장소에서 구성 요소를 분리하여 테스트 및 재사용을 더 쉽게 만들 수 있습니다.

결합된 API에서 구현 코드는 약간 다릅니다. 여기서는 MovieList.vue 페이지를 예로 들었습니다. 다른 페이지는 유사한 방식으로 작성되었으며 표시되지 않습니다. MovieList.vue 페이지의 코드는 다음과 같습니다. :

<!-- components/MovieList.vue -->

<template>
  <ul>
    <li v-for="movie in movies" :key="movie.id">
      <router-link :to="`/movies/${
      
      movie.id}`">{
    
    {
    
     movie.title }}</router-link>
    </li>
  </ul>
</template>

<script setup>
import {
    
     onMounted, computed } from 'vue'
import {
    
     useStore } from 'pinia'

const store = useStore('movie')

onMounted(() => {
  store.fetchMovies()
})

const movies = computed(() => store.getMovies())
</script>

이상으로 Vue3에서 글로벌 상태 관리를 위한 Pinia 사용에 대한 소개를 마칩니다.

추천

출처blog.csdn.net/w137160164/article/details/131160122