豆
-
pinia は本質的にモジュール化をサポートしています
-
コンポーザブル API はネイティブにサポートされています
ピニアとvuexの比較
pinia と Vuex はどちらも Vue.js 状態管理ライブラリです
- API の違い: Pinia は Vuex に似た API を提供しますが、Vuex の方がシンプルで直感的に使用できます。たとえば、Ponia は
defineStore
定義ストアを使用しますが、Vuex はnew Vuex.Store
定義ストアを使用します。 - データの応答性の違い: Pinia は Vue 3 の応答システムを使用しますが、Vuex は Vue 2 の応答システムを使用します。Vue 3 の応答性の高いシステムは、より効率的かつ柔軟です。
- さまざまなプラグイン: Vuex には、機能を簡単に拡張できるサードパーティのプラグインが多数あります。Pinia はまだ比較的若いですが、現在利用できるプラグインは比較的少数です。
- TypeScript のサポート: Pinia は TypeScript のサポートが優れており、TypeScript の型チェック機能をより有効に活用できますが、Vuex の型推論は比較的弱いです。全体として、Ponia はよりシンプルで直感的な API を提供し、Vue 3 の反応性システムを使用していますが、そのエコシステムは比較的小規模です。一方、Vuex には、より豊富なエコシステムとプラグインがあり、Vue 2 と TypeScript のサポートが強化されています。使用する状態管理ライブラリを選択するときは、特定のプロジェクト要件と開発チームのテクノロジー スタックに従って選択する必要があります。
どの状態管理ライブラリを使用するかは、プロジェクトの要件と個人的な好みに基づいて決定する必要があります。
使用
pinia 永続プラグインをmain.jsにインポートし、pinia をインスタンス化し、pinia が永続ストレージ プラグインを使用できるようにします。
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
//导入pinia持久化插件
import piniaPluginPersistedstate from "pinia-plugin-persistedstate"; //pinia持久化
const app = createApp(App)
//实例化pinia
var pinia = createPinia()
pinia.use( piniaPluginPersistedstate );
app.use( pinia )
app.mount('#app')
これは vuex とは異なり、pinia はパイナップルのような、各モジュールです。モジュール管理の必要がなく、独立したモジュールなので管理が容易です。
例: sc.js ファイル
// 导入vue中的ref:可以将基本数据类型和引用数据类型转换成 响应式数据
// 导入计算属性
import {ref, computed} from 'vue'
import {defineStore } from 'pinia'
// 你可以对 `defineStore()` 的返回值进行任意命名,但最好使用 store 的名字,同时以 `use` 开头且以 `Store` 结尾。(比如 `useUserStore`,`useCartStore`,`useProductStore`)
// 第一个参数是你的应用中 Store 的唯一 ID。
// 定义一个模块
export const usescStore = defineStore('sc',()=>{
// 定义响应式数据
const sc = ref([])
var add = (payload) => {
sc.value.push(10,payload)
}
return{
sc,
add
}
},{persist:true})
古典的なケースの todolist ロジック:::
tl.js ファイル
// 组合式写法:导入vue中ref和computed计算属性
// ref可以将基本数据类型和引用数据类型转换成=>响应式数据
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
// 定义一个模块
export const usetlStore = defineStore('tl', () => {
// 定义响应式数据
const tasklist = ref([])
// 定义计算方法
const finishCount = computed(() => {
return tasklist.value.filter(item => item.status == true).length
})
const unfinishCount = computed(() => {
return tasklist.value.filter(item => item.status == false).length
})
// 添加一个任务
var addTask = (payload) => {
let obj = {
id: tasklist.value.length + 1,
name: payload,
status: false,
}
tasklist.value.push(obj)
// console.log(tasklist.value);
}
// 更改任务的状态
var changeStatus = (payload) => {
let task = tasklist.value.find(item => item.id == payload)
if (task) {
task.status = !task.status;
}
}
// 删除任务
var deleteTask = (payload) => {
let i = tasklist.value.findIndex(item => item.id == payload)
if (i != -1) {
tasklist.value.splice(i, 1)
}
}
//请求任务列表数据
var request_tasklist = () => {
// 用计时器模拟ajax请求
setTimeout(() => {
var arr = [
{ id: 1, name: 'vuejs', status: false },
{ id: 2, name: 'reactjs', status: false },
]
tasklist.value = arr
}, 1000)
}
return {
tasklist,
finishCount,
unfinishCount,
addTask,
request_tasklist,
changeStatus,
deleteTask,
}
}, { persist: true })
// 开启可持续化存储
ページレイアウト:
SearchCom.vue
<template>
<div class="search-box">
<input type="text" placeholder="输入任务名称" v-model="name"> <button @click="add">添加</button>
</div>
<!-- {
{ scStore.sc }} -->
</template>
<script>
import { ref } from 'vue'
import { usetlStore } from '@/stores/tl'
import { usescStore } from '@/stores/sc'
export default {
setup() {
// 获取模块实例
let tlStore = usetlStore()
let scStore = usescStore()
let name = ref('')
let add = () => {
if (name.value) {
// 调用模块中的方法,新增任务
tlStore.addTask(name.value)
// 点击清空输入框
scStore.add(name.value)
name.value = ''
}
}
return {
name,
tlStore,
scStore,
add,
}
}
}
</script>
<style scope>
.search-box {
margin: 10px;
display: flex;
align-items: center;
}
.search-box input {
flex: 1;
height: 40px;
background-color: #f5f5f5;
border-radius: 20px;
padding-left: 20px;
outline: none;
border: none;
}
.search-box button {
width: 60px;
text-align: center;
height: 40px;
outline: none;
appearance: none;
border: none;
background-color: transparent;
}
</style>
概要.vue
<template>
<div class="summary">
<span>全部任务( {
{ tlStore.tasklist.length }} )</span>
<span>已完成{
{ tlStore.finishCount }}</span>
<span class="unfinish">未完成{
{ tlStore.unfinishCount }}</span>
</div>
</template>
<script>
// 导入模块
import { usetlStore } from '@/stores/tl'
export default{
setup(){
// 获取模块实例
var tlStore = usetlStore()
return{
tlStore
}
}
}
</script>
<style scoped>
.summary{
display: flex;
justify-content: space-between;
align-items: center;
}
.summary span{
padding: 5px 20px;
text-align: center;
color: white;
background-color: lightseagreen;
border-radius: 5px;
font-size: 14px;
}
.summary span.unfinish{
background-color: red;
}
</style>
List.vue
<template>
<div class="list">
<div class="title">任务列表</div>
<div :class="{task:true,unfinish:item.status}" v-for="(item,index) in tlStore.tasklist" :key="index">
<div class="left">
<input type="checkbox" :checked="item.status" @click="change(item.id)">
<span>{
{ item.id }} </span>
<span>{
{ item.name }} </span>
</div>
<span @click="del(item.id)">删除</span>
</div>
</div>
</template>
<script>
// 导入模块
import {usetlStore} from '@/stores/tl'
export default {
setup() {
// 获取模块实例
var tlStore = usetlStore()
// 定义方法
var change = (id)=>{
tlStore.changeStatus(id);
}
var del = (id)=>{
tlStore.deleteTask(id)
}
return {
tlStore,
change,
del
}
}
}
</script>
<style scoped>
.list .title {
font-weight: bold;
margin: 20px 0;
}
.list .task {
display: flex;
justify-content: space-between;
align-items: center;
color: white;
font-size: 14px;
padding: 10px;
margin: 10px 0;
background-color: lightseagreen;
}
.list .task.unfinish {
background-color: red;
}
</style>