pinia
-
pinia天生支持模块化
-
天生支持组合式api
pinia 和 vuex对比
pinia和Vuex都是Vue.js状态管理库
- API的不同:Pinia提供了类似于Vuex的API,但使用起来更加简单直观。例如,Pinia使用
defineStore
定义store,而Vuex使用new Vuex.Store
定义store。 - 数据响应式的不同:Pinia使用Vue 3的响应式系统,而Vuex使用Vue 2的响应式系统。Vue 3的响应式系统更加高效和灵活。
- 插件的不同:Vuex具有很多第三方插件,可以很方便地扩展其功能。而Pinia还比较年轻,目前可用的插件相对较少。
- TypeScript的支持:Pinia对TypeScript的支持更好,可以更好地利用TypeScript的类型检查功能,而Vuex的类型推断相对较弱。 总的来说,Pinia提供了一个更加简单和直观的API,并且使用Vue 3的响应式系统,但它的生态系统相对较小。而Vuex则具有更加丰富的生态系统和插件,并且对Vue 2和TypeScript的支持更好。在选择使用哪一个状态管理库时,需要根据具体项目需求和开发团队的技术栈来进行选择。
具体使用哪个状态管理库应该根据项目需求和个人喜好来决定。
使用
main.js中导入pinia持久化插件,实例化pinia,
开启pinia使用持久化存储插件:
npm i pinia-plugin-persistedstate
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就像菠萝一样,一个个模块。不用进行模块化管理,自己就是独立模块,更加便于管理。
eg: 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>
Summary.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>