Pinia 는 Vue.js 애플리케이션의 구성 요소에서 반응형 데이터와 상태를 관리하고 저장하는 데 도움이 되는 새로운 상태 관리 라이브러리입니다. Pinia는 Vue 핵심 팀원 중 한 명인 Eduardo San Martin Morote가 만들었습니다.
피니아는 새로운 반응성 시스템을 사용하여 직관적이고 완전한 유형이 적용된 상태 관리 시스템을 구축합니다.
라이브러리에 도입된 새로운 기능은 Pinia의 추천에 기여하는 요인 중 하나입니다. 전반적으로 Pinia는 가볍고 복잡하지 않으며 마스터하기 쉽습니다. Vue 3 및 Vue 2에서 프로그래밍을 다재다능하게 만들 수 있는 모든 것을 갖추고 있습니다. 따라서 Pinia를 사용해 볼 수 있는 이상적인 기회입니다.
Pinia와 Vuex의 차이점 중 하나는 Pinia가 "모듈식 설계"라는 것입니다. 즉, 여러 개의 매장을 갖도록 구축된 반면 Vuex는 매장이 하나뿐입니다. 이러한 매장 내부에는 하위 모듈을 둘 수 있습니다. 그 외에도 Pinia는 이러한 각 모듈을 필요한 경우 매장에서 직접 구성 요소로 가져올 수 있습니다.
import Vue from 'vue'
import Vuex, { ActionTree, GetterTree, MutationTree } from 'vuex'
import { filterTypes, State, TodoItem } from './types'
Vue.use(Vuex)
const state: State = {
todos: [],
activeFilter: filterTypes[0],
}
const getters: GetterTree<State, any> = {
allTodos: state => state.todos,
}
const mutations: MutationTree<State> = {
addTodo(state, txt: string) {
if (state.todos.map(todo => todo.txt).indexOf(txt) === -1) {
state.todos.push({
txt,
done: false,
})
}
},
toggleTodo(_state, todo: TodoItem) {
todo.done = !todo.done
},
deleteTodo(state, todo: TodoItem) {
state.todos.splice(state.todos.indexOf(todo), 1)
},
selectFilter(state, {filter}) {
state.activeFilter = filter
},
}
const actions: ActionTree<State, State> = {
selectFilter({commit}, filter) {
commit('selectFilter', { filter })
},
}
export default new Vuex.Store({
state,
getters,
mutations,
actions,
})
// 사용
import Vue from 'vue'
import Component from 'vue-class-component'
import { Mutation, State } from 'vuex-class'
import Todo from './components/Todo'
import TodoFilter from './components/TodoFilter'
import store from './store/index'
import { TodoItem } from './store/types'
import WithRender from './templates/app.html'
@WithRender
@Component({
components: {
Todo, TodoFilter,
},
})
export default class App extends Vue {
name: string = 'App'
input: string = ''
filters: any = {
ALL: (todos: TodoItem[]) => todos,
ACTIVE: (todos: TodoItem[]) => todos.filter((todo: TodoItem) => !todo.done),
COMPLETED: (todos: TodoItem[]) => todos.filter((todo: TodoItem) => todo.done),
}
@State todos: TodoItem[]
@State activeFilter: string
@Mutation toggleTodo: (todo: TodoItem) => void // Best would be if this could derive the type automatically
@Mutation deleteTodo: any
get filteredTodos() {
return this.filters[this.activeFilter](this.todos)
}
addTodo(): void {
if (!this.input.trim().length) {
return
}
this.$store.commit('addTodo', this.input.trim())
this.input = ''
}
}
import { computed, ref } from 'vue';
import { defineStore } from 'pinia';
import type { ITodo } from '@/interfaces';
function toggleProp(prop: 'important' | 'done', id: string, todo: ITodo) {
return todo.id === id ? { ...todo, [prop]: !todo[prop] } : todo;
}
export const useTodoStore = defineStore('todo', () => {
const todos = ref<ITodo[]>([]);
function addTodo(todo: ITodo) {
todos.value.push(todo);
}
function removeTodo(id: string) {
todos.value = todos.value.filter((todo: ITodo) => todo.id !== id);
}
function toggleDone(id: string) {
todos.value = todos.value.map((todo) => toggleProp('done', id, todo));
}
function toggleImportant(id: string) {
todos.value = todos.value.map((todo) => toggleProp('important', id, todo));
}
const doneTodosCount = computed(() => todos.value.filter((todo) => todo.done).length);
const importantTodosCount = computed(() => todos.value.filter((todo) => todo.important).length);
const activeTodosCount = computed(() => todos.value.filter((todo) => !todo.done).length);
return {
addTodo,
removeTodo,
toggleDone,
toggleImportant,
doneTodosCount,
importantTodosCount,
activeTodosCount,
todos
};
});
// 사용
<script setup lang="ts">
import { Input, List, ListItem, Typography } from 'ant-design-vue';
import { ref } from 'vue';
import { useTodoStore } from '@/stores/todo';
import { v4 as uuidv4 } from 'uuid';
import CloseCircleOutlined from '@ant-design/icons-vue/lib/icons/CloseCircleOutlined';
import CheckOutlined from '@ant-design/icons-vue/lib/icons/CheckOutlined';
import ExclamationOutlined from '@ant-design/icons-vue/lib/icons/ExclamationOutlined';
const field = ref('');
const store = useTodoStore();
function createTodo(text: string) {
return { text, id: uuidv4(), done: false, important: false };
}
function handleAddTodo() {
const todo = createTodo(field.value);
store.addTodo(todo);
field.value = '';
}
</script>
this.$store.commit('addTodo', this.input.trim())store.addTodo(todo);<List bordered :data-source="store.todos">위 3가지의 차이점만 봐도 pinia를 사용하면 vuex보다 직관적인 코드의 작성이 가능하다고 생각됩니다.
1년 전부터 알고있던 라이브러리지만 코드로 직접 비교해서 보니까 도 다르군요
bundlephobia 번들링 사이즈
https://www.telerik.com/blogs/vue-js-state-management-pinia-vs-vuex
https://github.com/johnygomez/vue-vuex-typescript-example
https://github.com/kamenivskyi/todo-pinia-example