Pinia和Vuex的对比
与Vuex相比,Pinia提供了一个更简单的API,具有更少的仪式,提供了Composition-API风格的API
最重要的是,在与TypeScript一起使用时具有可靠的类型推断支持
- 比如mutation不再存在
- 更有好的TypeScript支持
- 不再有modules的嵌套结构,可以灵活使用每一个store,他们是通过扁平化的方式来相互使用的
创建Pinia的Store
// store中index.js
import { createPinia } from 'pinia'
const pinia = createPinia()
export default pinia
// 定义关于counter的store counter.js
import { defineStore } from 'pinia'
import useUser from './user'
const useCounter = defineStore("counter", { //参数"counter"是必要的,用来连接到devtool
...
})
export default useCounter
//template中使用,直接store.***,不需要加state
<h2>count: {{ counterStore.count }}</h2>
import useCounter from '@/stores/counter';
const counterStore = useCounter()
---------------------------------------------------------------
注意:在template中使用的时候,用store.***的方式直接调用,是响应式的,也可以用解构的方式:
`const { count } = counterStore`,这样在template中直接使用`count`,
但这种方式不是响应式的,如果想要这种方式变成响应式的,需要使用`toRefs`,修改代码为:
`const { count } = toRefs(counterStore)`;
另外,在pinia中,也提供了一种方式:
import { storeToRefs } from 'pinia'
const { count } = storeToRefs(counterStore)
效果和toRefs是一样的,无论哪种方法都可以实现
另:返回的函数统一使用useX作为命名方案,这是约定的规范
----------------------------------------------------------------
如果需要触发方法修改state中的参数,不需要提交mutation,直接修改即可:
function incrementCount() {
counterStore.count++
}
在pinia中,可以定义任意数量的store来管理状态
store的三个核心概念:
- state、getters、actions
- 等同于组建的data、computed、methods
- 一旦store被实例化,就可以直接在atore上访问state、gettres和actions的定义的任何属性
Pinia核心概念State
1、重置State
import useUser from '@/stores/user'
const userStore = useUser()
function resetState() {
userStore.$reset()
}
2、修改state
// 1.一个个修改状态
function changeState() {
userStore.name = "kobe"
userStore.age = 20
userStore.level = 200
}
// 2.一次性修改多个状态
function changeState() {
userStore.$patch({
name: "james",
age: 35
})
}
// 3.替换State为新的对象
function changeState() {
const oldState = userStore.$state
userStore.$state = {
name: "curry",
level: 200
}
console.log(oldState === userStore.$state) //true
}
Pinia核心概念Getters
1、基本使用
//counter.js
doubleCount(state) {
return state.count * 2
},
//template
<h2>doubleCount: {{ counterStore.doubleCount }}</h2>
import useCounter from '@/stores/counter';
const counterStore = useCounter()
2、一个getter引入另外一个getter
doubleCount(state) {
return state.count * 2
},
doubleCountAddOne() {
// this是store实例
return this.doubleCount + 1
},
3、getters也支持返回一个函数
getFriendById(state) {
return function(id) {
for (let i = 0; i < state.friends.length; i++) {
const friend = state.friends[i]
if (friend.id === id) {
return friend
}
}
}
},
4、getters中用到别的store中的数据
//顶部先引入
import useUser from './user'
//使用
showMessage(state) {
// 1.获取user信息
const userStore = useUser()
// 2.获取自己的信息
// 3.拼接信息
return `name:${userStore.name}-count:${state.count}`
}
Pinia核心概念Actions
和getters一样,在action中可以通过this访问整个store实例的所有操作
基本使用
//template
<h2>doubleCount: {{ counterStore.count }}</h2>
<button @click="changeState">修改state</button>
import useCounter from '@/stores/counter';
const counterStore = useCounter()
function changeState() {
// counterStore.increment()
counterStore.incrementNum(10)
}
//counter.js
actions: {
increment() {
this.count++
},
incrementNum(num) {
this.count += num
}
}
发送异步请求
//展示数据
<h2>轮播的数据</h2>
<ul>
<template v-for="item in homeStore.banners">
<li>{{ item.title }}</li>
</template>
</ul>
import useHome from '@/stores/home';
const homeStore = useHome()
homeStore.fetchHomeMultidata().then(res => {
console.log("fetchHomeMultidata的action已经完成了:", res)
})
//home.js
actions: {
async fetchHomeMultidata() {
const res = await fetch("http://123.207.32.32:8000/home/multidata")
const data = await res.json()
this.banners = data.data.banner.list
this.recommends = data.data.recommend.list
}
}