0. Предисловие
Pinia — это предложение протестировать следующую итерацию Vuex.
Предложение Vuex5, большое улучшение по сравнению с Vuex3 и 4
- служба поддержки
options apiandcomposition api - нет
mutations - нет вложенных модулей
- лучше
typescriptслужба поддержки - Автоматическое разделение кода
1. Сравнение с Vuex
Pinia пытается максимально приблизиться к философии Vuex. Он был разработан для проверки предложений по следующей итерации Vuex, и он прошел успешно, в настоящее время существует открытый RFC для Vuex 5,Его API иAPI, используемый Pinia, очень похож. Обратите внимание, что автор Pinia I (Эдуардо) является частью основной команды Vue.js и активно участвует в разработке таких API, как Router и Vuex. Цель этого проекта заключалась в том, чтобы изменить опыт использования глобального хранилища, сохранив при этом доступную философию Vue. Сближение API Pania с API Vuex по мере его дальнейшего развития упрощает переход на Vuex или даже объединение двух проектов в будущем.
API Pinia сильно отличается от Vuex ≤4:
- нет
mutations. мутации считаются очень подробными. Первоначально привнесена интеграция с devtools, но это уже не проблема. - Больше нет вложенной структуры модулей. Вы по-прежнему можете неявно вкладывать магазины, импортируя и используя магазин в другом магазине, но Pinia обеспечивает плоскую структуру по дизайну, при этом поддерживая кросс-композицию между магазинами. Вы даже можете иметь циклические зависимости магазинов.
- лучше
typescriptслужба поддержки. Нет необходимости создавать пользовательские сложные оболочки для поддержки TypeScript, все типизировано, а API разработан таким образом, чтобы максимально использовать вывод типа TS. - Больше не нужно внедрять, импортировать функции, вызывать их и наслаждаться автодополнением!
- Нет необходимости динамически добавлять магазины, они все динамические по умолчанию и вы даже не заметите. Обратите внимание, что вы по-прежнему можете вручную использовать магазин для его регистрации в любое время, но, поскольку это происходит автоматически, вам не нужно об этом беспокоиться.
- Модулей пространства имен нет. Учитывая плоскую архитектуру хранилищ, хранилище с "пространством имен" присуще способу его определения, можно сказать, что все хранилища имеют пространство имен.
2. Преимущества пинии
2.1 Интуитивно понятный
Магазины так же знакомы, как и компоненты. API предназначен для того, чтобы вы могли создавать хорошо организованные магазины.
2.2 Безопасность типа
Типы выводятся, что означает, что магазины предоставляют вам автозаполнение даже в JavaScript.
2.3 Поддержка инструментов разработчика
Pinia подключается к инструментам разработки Vue, чтобы обеспечить расширенный опыт разработки Vue 2 и Vue 3.
2.4 Расширяемый
Реагируйте на изменения хранилища, чтобы расширить Pinia транзакциями, синхронизацией локального хранилища и многим другим.
2.5 Модульная конструкция
Создайте несколько хранилищ и позвольте коду упаковщика разделить их автоматически.
2.6 Чрезвычайно легкий
Размер Pinia составляет около 1 КБ.
3. Основное использование
// stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => {
return { count: 0 }
},
// could also be defined as
// state: () => ({ count: 0 })
actions: {
increment() {
this.count++
},
},
})
в компонентеиспользоватьЭто:
import { useCounterStore } from '@/stores/counter'
export default {
setup() {
const counter = useCounterStore()
counter.count++
// with autocompletion ✨
counter.$patch({ count: counter.count + 1 })
// or using an action instead
counter.increment()
},
}
Вы даже можете использовать функции (аналогично компонентамsetup()), чтобы определить Store для более продвинутых вариантов использования:
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
function increment() {
count.value++
}
return { count, increment }
})
если незнакомыйsetup()Composition API, не волнуйтесь, Pania также поддерживает подобныепомощники карты для Vuex. Вы определяете магазины таким же образом, используяmapStores(), mapState(), илиmapActions():
const useCounterStore = defineStore('counter', {
state: () => ({ count: 0 }),
getters: {
double: (state) => state.count * 2,
},
actions: {
increment() {
this.count++
}
}
})
const useUserStore = defineStore('user', {
// ...
})
export default {
computed: {
// other computed properties
// ...
// gives access to this.counterStore and this.userStore
...mapStores(useCounterStore, useUserStore)
// gives read access to this.count and this.double
...mapState(useCounterStore, ['count', 'double']),
},
methods: {
// gives access to this.increment()
...mapActions(useCounterStore, ['increment']),
},
}