Vue3-Pinia的基本使用

Posted blackzjj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue3-Pinia的基本使用相关的知识,希望对你有一定的参考价值。

什么是Pinia呢?

Pina开始于大概2019,是一个状态管理的库,用于跨组件、页面进行状态共享(这和Vuex、Redux一样),用起来像组合式API(Composition API)

Pinia和Vuex的区别

  • PInia的最初是为了探索Vuex的下一次迭代会是什么样子,结合了Vuex核心团队讨论中的许多想法;
  • 最终,团队意识到Pinia已经实现了Vuex5中大部分内容,所以最终决定用Pinia来替代Vuex;
  • 与Vuex相比,Pinia提供了一个更简单的API,具有更少的仪式,提供了Composition-API风格的API
  • 更重要的是,与TypeScript一起使用时具有可靠的类型推断支持

与Vuex相比,Pinia很多的优势:

比如mutations不再存在:

  • mutations最初是为devtools集成,但这不在是问题
  • 他们经常认为是非常冗长

更友好的TpeScipt支持,Vuex之前对Ts的支持很不友好

不在有modules的嵌套结构

  • 你可以灵活使用每一个store,他们是通过扁平化的方式来相互使用的;

不在有命名空间的概念,不在需要记住他们的复杂关系

如何使用Pinia

1、安装Pinia

  • yarn add pinia
  • npm install pinia

2、创建pinia文件

store文件里index.js

import  createPinia  from 'pinia'

const pinia = createPinia()

export default pinia

3、main.js导入并引用

import  createApp  from 'vue'
import App from './App.vue'
import pinia from './stores'

createApp(App).use(pinia).mount('#app')

4、pinia的状态管理,不同状态可以区分不同文件

//定义关于counter的store
import  defineStore  from ‘pinia’

//defineStore 是返回一个函数 函数命名最好有use前缀,根据函数来进行下一步操作
const useCounter = defineStore('counter',
	state: () => 
		count:99
	
)

export default useCounter

5、调用pinia,获取pinia状态值,导入Counter.js,获取Counter.js里面state.count

<template>
  <div class="home">
    <h2>Home View</h2>
    <h2>count:  counterStore.count </h2>
  </div>
</template>

<script setup>
  import useCounter from '@/stores/counter';

  const counterStore = useCounter()

</script>

<style scoped>
</style>

注意:pinia解构出来的state也是可以调用,但会失去响应式,需要toRef或者pinia自带storeToRefs

<template>
  <div class="home">
    <h2>Home View</h2>
    <h2>count:  counterStore.count </h2>
    <h2>count:  count </h2>
    <button @click="incrementCount">count+1</button>
  </div>
</template>

<script setup>
  import  toRefs  from 'vue'
  import  storeToRefs  from 'pinia'
  import useCounter from '@/stores/counter';

  const counterStore = useCounter()

  // const  count  = toRefs(counterStore)
  const  count  = storeToRefs(counterStore)


  function incrementCount() 
    counterStore.count++
  

</script>

<style scoped>
</style>

store的核心部分:state,getter,action

相当于:data、computed、methods

认识和定义State

state是store的核心部分,因为store是用来帮助我们管理状态

操作State

  1. 读取和写入state:

    默认情况下,可以通过store实例访问状态来直接读取和写入状态;

    ```
    const counterStore = useCounter()
    
    counterStore.counter++
    counterStore.name = 'coderWhy'
    ```
    
  2. 重置State:
    可以调用store上的$reset()方法将状态重置到其初始值

    const counterStore = useCounter()
    conterStore.$reset()
    
  3. 改变State

    • 除了直接用store.counter++修改store,还可以调用$patch

    • 它允许您使用部分‘state’对象同时应该多个修改

    const counterStore = useCounter()
    
    counterStore.$patch(
    	counter:100,
    	name:'kobe'
    )
    
  4. 替换State
    可以通过将其$state属性设置为新对象替换Store的整个状态

    conterStore.$state = 
    	counter:1,
    	name:'why'
    
    

认识和定义Getters

  • Getters相当于Store的计算属性:

    1. 它们可用defineStore()中的getters属性定义
    2. getters中可以定义接受一个state作为参数的函数
    expoer const useCounter = defineStore('counter',
    	state: () => 
    		counter:100,
    		firstname:'kobe'
    	,
    	getters:
    		doubleCounter(state)
    			return state.counter *2
    		
    	
    )
    
  • 访问Store里getters方法

    1. 访问当前store的getters:

      const counterSotre = useCounter()
      console.log(counterStore.doublCounter)
      
    2. 我们可以使用this来访问当前的store实例中getters

      expoer const useCounter = defineStore('counter',
      	state: () => 
      		counter:100,
      		firstname:'kobe'
      	,
      	getters:
      		doubleCounter(state)
      			return state.counter *2
      		
      		doubleCounterAdd()
      			//this指向store
      			return this.doubleCounter +1 
      		
      	
      )
      
    3. 访问其它store的getters

      import useUser from ./user
      
      const userStore = useUser()
      
      expoer const useCounter = defineStore('counter',
      	state: () => 
      		counter:100,
      		firstname:'kobe'
      	,
      	getters:
      	//调用其它Store
      		doubleCounterUser()
      			return this.doubleCounter + userStore.umu
      		
      	
      )
      
    4. 通过getters可以返回一个函数,可以传参数

      expoer const useCounter = defineStore('counter',
      	state: () => 
      		counter:100,
      		firstname:'kobe'
      	,
      	getters:
      	//调用其它Store
      		doubleCounter(state)
      			return function (is) 
      				return state.id + id
      			
      		
      	
      )
      
      const StoreConter = useCounter();
      //传参
      StoreCounter.doublCounter(111)
      

认识和定义Actions

  • Actions 相当于组件中的methods,可以使用defineStore()中的actions属性定义

    expoer const useCounter = defineStore('counter',
    	state: () => 
    		counter:100,
    		firstname:'kobe'
    	,
    	getters:
    	//调用其它Store
    		doubleCounter(state)
    			return function (is) 
    				return state.id + id
    			
    		
    	,
    	actions:
    		increment()
    			this.counter++
    		,
    		//传参
    		incrementnum(num)
    			this。counter += num
    		
    	
    )
    

    和getters一样,在action中可以通过this访问整个store实例:

    function increment()
    	//调用
    	counterStore.increment()
    
    function incrementnum()
    	counterStore.increment(10)
    
    

Actions执行异步操作:

  • Actions中是支持异步操作的,并且我们可以编写异步函数,在函数中使用await

    actions:
    	async fetchHome()
    		//???请求
    		const res = await fetch('?????')
    		const data = await res.json()
    		console.log('data',data)
    		return data
    	
    
    
    cosnt counterStore = useCounter
    
    counterStore.fetchHome().then(res => 
    	console.log(res)
    )
    

Vue3 pinia 的使用

yarn add pinia

引入后导入main.ts

import createApp from 'vue'
// import './style.css'
import App from './App.vue'
import CardVue from './components/Card.vue'
import createPinia from "pinia";
const store=createPinia()

export const app = createApp(App)
app.component('CardVue', CardVue)
app.use(store)
app.mount('#app')

使用

 先创建俩这个文件

export const enum Names
    TEST='test'
import defineStore from "pinia";
import Names from "./store-name";

export const useTestStore = defineStore(Names.TEST, 
    state: () => 
        return 
            current: 10,
            name: "anguo"
        
    ,
    //类似 computed 修饰一些数值
    getters: ,
    //类似 methods 可以做同步异步 提交state
    actions: 
        setCurrent() 
            this.current = 999
        
    
)

内容如下

使用

<template>
  <div>
    pinia: Test.current  --  Test.name 

    <button @click="change">change</button>
  </div>
  <div>

    pinia: current  --  name 
  </div>

</template>

<style scoped>
#app, html, body 

  height: 100%;


* 
  padding: 0;
  margin: 0;


.tabs 
  border: 1px solid #CCC;
  padding: 5px 10px;
  margin: 10px;
  cursor: pointer;


.active 
  background: skyblue;


</style>

<script setup lang="ts">

import useTestStore from "./store";

import storeToRefs from "pinia";

const Test = useTestStore()
//默认不具有响应式,如果想要响应式需要包裹一下storeToRefs
const current, name = storeToRefs(Test)

const change = () => 
  //修改painia的值 的五种方法
  //第一种 可以直接进行修改
  // Test.current++
  // Test.name = '我是谁'
  //第二种修改方式
  // Test.$patch(
  //   current: Test.current + 1,
  //   name: '我是谁'
  // )
  //第三种修改方式
  // Test.$patch((state) => 
  //   state.current++
  //   state.name = '我是谁'
  //
  // )
  //第四种修改方式 修改整个对象 不是很推荐 缺陷要修改所有值
  // Test.$state = 
  //   current: 2000,
  //   name: "1324"
  // 
  //第五种 借助action去修改
  // Test.setCurrent()
  //对对象进行解构 不具有响应式的 可以使用storeToRefs 对其进行包裹然后就具有响应式了
  Test.current++
  current.value++
  console.log(current, name)

</script>

效果

 针对异步的修改,actions的方法可以互相调用

index.ts
import defineStore from "pinia";
import Names from "./store-name";

type User = 
    name: string,
    age: number

let result: User = 
    name: "anguo",
    age: 18


const Login = (): Promise<User> => 
    return new Promise((resolve) => 
        setTimeout(() => 
            resolve(result)
        , 2000)
    )

export const useTestStore = defineStore(Names.TEST, 
    state: () => 
        return 
            user: <User>,
            name: "defalut name",
        
    ,
    //类似 computed 修饰一些数值
    getters: ,
    //类似 methods 可以做同步异步 提交state
    actions: 
        //同步修改
        setUser() 
            this.user = result;
        ,
        //异步修改
        async setUserAsync() 
            const result = await Login()
            this.user = result
            this.setName("new name")
        ,
        setName(name: string) 
            this.name = name
        
    
)

App.vue

<template>
  <div>
    <p>actions-users: Test.user </p>
    <hr>
    <p>actions-name: Test.name </p>
    <hr>
    <p>getters:</p>
    <hr>
    <button @click="change">change</button>

  </div>


</template>

<style scoped>
#app, html, body 

  height: 100%;


* 
  padding: 0;
  margin: 0;


.tabs 
  border: 1px solid #CCC;
  padding: 5px 10px;
  margin: 10px;
  cursor: pointer;


.active 
  background: skyblue;


</style>

<script setup lang="ts">

import useTestStore from "./store";

import storeToRefs from "pinia";

const Test = useTestStore()
//默认不具有响应式,如果想要响应式需要包裹一下storeToRefs

const change = () => 
  //同步
  // Test.setUser()
  //异步
  Test.setUserAsync()

</script>

 getters

import defineStore from "pinia";
import Names from "./store-name";

type User = 
    name: string,
    age: number

let result: User = 
    name: "anguo",
    age: 18


const Login = (): Promise<User> => 
    return new Promise((resolve) => 
        setTimeout(() => 
            resolve(result)
        , 2000)
    )

export const useTestStore = defineStore(Names.TEST, 
    state: () => 
        return 
            user: <User>,
            name: "defalut name",
        
    ,
    //类似 computed 修饰一些数值
    getters: 
        getName(): string 
            return `$-$this.name-$this.getUserAge`
        ,
        getUserAge(): number 
            return this.user.age
        
    ,
    //类似 methods 可以做同步异步 提交state
    actions: 
        //同步修改
        setUser() 
            this.user = result;
        ,
        //异步修改
        async setUserAsync() 
            const result = await Login()
            this.user = result
            this.setName("new name")
        ,
        setName(name: string) 
            this.name = name
        
    
)

app.vue

<template>
  <div>
    <p>actions-users: Test.user </p>
    <hr>
    <p>actions-name: Test.name </p>
    <hr>
    <p>getters: Test.getName</p>
    <hr>
    <button @click="change">change</button>

  </div>


</template>

<style scoped>
#app, html, body 

  height: 100%;


* 
  padding: 0;
  margin: 0;


.tabs 
  border: 1px solid #CCC;
  padding: 5px 10px;
  margin: 10px;
  cursor: pointer;


.active 
  background: skyblue;


</style>

<script setup lang="ts">

import useTestStore from "./store";

import storeToRefs from "pinia";

const Test = useTestStore()
//默认不具有响应式,如果想要响应式需要包裹一下storeToRefs

const change = () => 
  //同步
  // Test.setUser()
  //异步
  Test.setUserAsync()

</script>

以上是关于Vue3-Pinia的基本使用的主要内容,如果未能解决你的问题,请参考以下文章

美团开源用 Vue.js 开发小程序的前端框架 mpvue

vue单向以及双向数据绑定(v-bind和v-model使用)

vue单向以及双向数据绑定(v-bind和v-model的使用)

vue单页面程序

nuxt实践

《Vue.Js》基本使用