【学习vite + vue3 + pinia + ts】pinia应用 store的创建及应用

在根目录下新建store文件夹,在文件夹下新建index.ts文件

一. src>>store>>index.ts文件中创建store

import { defineStore } from 'pinia'

interface State { }

export const useUserStore = defineStore('main', {
  state: ():State => ({ }),
  //类似于computed
  getters: { },
  //类似于methods
  actions: { }
})

二.在组件中应用store 

<template>
  <div class="page">
    用户名: {{user.name}}
    <a-button type="primary" @click="changeName">修改用户名</a-button>
  </div>
</template>

1. 读取state中的属性

<script setup lang="ts">
  import { useUserStore } from '@/store'
  const user = useUserStore()
</script>

2.state值的六种改变方式

(1)直接修改

<script setup lang="ts">
  import { useUserStore } from '@/store'
  const user = useUserStore()
  const changeName = () =>{
    user.name = '后端'
  }
</script>

(2)$patch批量修改

该修改方式需要定义store的时候,并没有对state函数返回值做类型限制,且批量修改只能修改state函数返回值中已存在的属性

<script setup lang="ts">
  import { useUserStore } from '@/store'
  const user = useUserStore()
  const changeName = () =>{
    user.$patch({
      name: 'vue',
      age: 4,
    })
  }
</script>

(3)$patch带逻辑修改

该中方式支持创建store时对state函数返回值类型限定

-- 若限定中可以有任意属性,则可以添加state中没有的属性

-- 若没有返回值类型限定,则只能修改创建state时已存在的属性

<script setup lang="ts">
  import { useUserStore } from '@/store'
  const user = useUserStore()
  const changeName = () =>{
    user.$patch(state => {
      if(..){
        state.name = 'react'
        state.type = '前端'
      }
    })
  }
</script>

(4)$state替换state

<script setup lang="ts">
  import { useUserStore } from '@/store'
  const user = useUserStore()
  const changeName = () =>{
    user.$state = {
      userId: '666',
      name: 'vscode',
      age: 18
    }
  }
</script>

(5)借助actions方法

src>>store>>index.ts

actions: {
  changName(name:string){
    this.name = name
  }
}

组件中

<script setup lang="ts">
  import { useUserStore } from '@/store'
  const user = useUserStore()
  const changeName = () =>{
    user.changName('333')
  }
</script>

(6)使用$reset重置state 

const store = useStore()
store.$reset()

3.借助 storeToRefs 解构state

<script setup lang="ts">
  import { storeToRefs } from "pinia";
  import { useUserStore } from '@/store'
  const { name } = storeToRefs(useUserStore())
  const changeName = () =>{
    name.value = '111'
  }
</script>

4. actions

可以直接this.xx访问到state中的属性,也可以this.xxx访问到actions中的方法

(1) 处理同步逻辑

actions: {
  changName(name:string){
    this.name = name
  },
}

(2) 处理异步逻辑

import { defineStore } from 'pinia'

interface User {
  userId: string,
  name: string,
  age: number,
  [propName: string]: any
}

const login = ():Promise<User> => {
  return new Promise(resolve => {
    setTimeout(()=>{
      resolve({
        userId: '666',
        name: '333',
        age: 4
      })
    },1000)
  })
}

export const useUserStore = defineStore('main', {
  state: () => {
    return {
      user: <User>{}
    }
  },
  //类似于computed
  getters: {

  },
  //类似于methods
  actions: {
    changName(name:string){
      this.user.name = name
    },
    async setUser(){
      const userInfo = await login()
      this.user = userInfo
    }
  }
})

5.getters

需要定义返回类型,可以在定义常规函数时通过this访问到 整个 store 的实例

(1)函数式写法

//类似于computed
getters: {
  enName():string{
    return this.user.name
  }
},

(2)接收参数 

state: () => {
  let users: Array<User> = []
  return {
    user: <User>{},
    users,
  }
},
//类似于computed
getters: {
  getUserById: (state) => {
    return (userId:string) => state.users.find((user) => user.id === userId)
  }
},

组件中应用

<template>
  <div class="page">
    用户名: {{store.user.name}}<br>{{store.users}}<br> {{ store.getUserById('666') }}
    <br>
    <a-button style="margin-right:10px" type="primary" @click="changeName">修改用户名</a-button>
    <a-button type="primary" @click="addUser">添加用户名</a-button>
  </div>
</template>

<script setup lang="ts">
  import { useUserStore } from '@/store'
  const store = useUserStore()
  const changeName = () =>{
    store.user.name = 'vue'
  }
  const addUser = () =>{
    const user = {
      userId: '666',
      name: 'react',
      age: 4
    }
    store.users.push(user)
  }
</script>

6.组件中对store实例方法的使用

(1)借助$subscribe监测state值的变化 

state中的值发生改变,则会触发 $subscribe 函数,接收一个箭头函数,箭头函数会内部传递两个参数,第一个参数为对变化的监控,第二个参数为修改后的state

store.$subscribe((arg, state)=>{
  console.log('**',arg)
  console.log('==',state)
},{ //第二个参数为配置对象
  detached: true, //组件销毁后依然监测state值的变化
  deep: true, //深度监测
  flush: 'post', //回调的刷新时机 pre默认值,dom更新前调用 sync同步调用 post dom更新后调用
  immediate: true, //立即触发一次
})

(2)借助$onAction监测actions中方法的调用

store.$onAction(arg=>{
  console.log('//', arg)
  arg.after(()=>{
    console.log('123')
  })
}, true) //true为第二个参数,可以不写,写上表示组件销毁后依然监测actions的调用情况

三.借助插件实现持久化保存数据(刷新不丢失)

同vuex一样,刷新页面的时候,store中的数据会重置为初始化,但是pinia支持通过插件将数据保存到 localStorage/sessionStorage/cookie 中

1. src>>plugins>>piniaPlugin.ts

import { PiniaPluginContext } from 'pinia'
import { toRaw } from 'vue'

type Options = {
  key?: string,
  type?: string
}

const _piniaKey:string = 'pinia'
const _type = 'session'

const setStorage = (key:string, value: any, type:string) => {
  switch (type) {
    case 'session':
      sessionStorage.setItem(key, JSON.stringify(value))
      break
    case 'local':
      localStorage.setItem(key, JSON.stringify(value))
      break
  }
}
const getStorage = (key:string, type:string) => {
  let data:any
  switch (type) {
    case 'session':
      data = sessionStorage.getItem(key) ? JSON.parse(sessionStorage.getItem(key) as string) : {}
      break
    case 'local':
      data = localStorage.getItem(key) ? JSON.parse(localStorage.getItem(key) as string) : {}
      break
  }
  return data
}

const piniaPlugin = (option: Options) => {
  return (context: PiniaPluginContext) => {
    const { store } = context
    const data = getStorage(`${option?.key ?? _piniaKey}-${store.$id}`, `${option?.type ?? _type}`)
    store.$subscribe(() => {
      setStorage(`${option?.key ?? _piniaKey}-${store.$id}`, toRaw(store.$state), `${option?.type ?? _type}`)
    })
    return {
      ...data
    }
  }
}
export default piniaPlugin

2.修改mian.ts

import { createApp } from 'vue'
import App from './App.vue'
import router from '@router/index'
import { createPinia } from 'pinia'
import piniaPlugin from './plugins/piniaPlugin'

const store = createPinia()
store.use(piniaPlugin(
  {
    key: 'pinia',
    type: 'local'
  }
))

const app = createApp(App)

app
.use(store)
.use(router)
.mount('#app')

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
对于使用 Vite + Vue3 + TypeScript + Pinia + Vue Router + Axios + SCSS 并自动导入 API 的设置,你可以按照以下步骤进行操作: 1. 首先,确保你已经安装了 Node.js,并且版本大于等于 12.0.0。 2. 创建一个新的 Vue 项目,可以使用 Vue CLI 或者手动创建一个空文件夹。 3. 在项目根目录下,打开终端并执行以下命令安装 Vite: ```bash npm init vite@latest ``` 按照提示选择你的项目配置,包括选择 Vue 3、TypeScript 和其他选项。 4. 进入项目目录并安装依赖: ```bash cd your-project-name npm install ``` 5. 安装 Pinia 插件: ```bash npm install pinia ``` 6. 创建一个 `src/store` 目录,并在其创建 `index.ts` 文件,用于定义和导出你的 Pinia store。 ```typescript // src/store/index.ts import { createPinia } from 'pinia' export const store = createPinia() // 可以在这里定义你的 store 模块 ``` 7. 在项目根目录下创建 `src/api` 目录,用于存放 API 请求相关的文件。 8. 在 `src/api` 目录下创建一个 `index.ts` 文件,用于自动导入所有 API 文件。 ```typescript // src/api/index.ts const modules = import.meta.globEager('./*.ts') const apis: any = {} for (const path in modules) { if (path !== './index.ts') { const moduleName = path.replace(/^.\/|\.ts$/g, '') apis[moduleName] = modules[path].default } } export default apis ``` 这样,你就可以在 `src/api` 目录下创建各种 API 请求的文件,例如 `user.ts`: ```typescript // src/api/user.ts import axios from 'axios' export function getUser(id: number) { return axios.get(`/api/user/${id}`) } ``` 然后,在你的组件使用自动导入的 API: ```typescript import { defineComponent, ref } from 'vue' import { useUserStore } from '@/store' import apis from '@/api' export default defineComponent({ setup() { const userStore = useUserStore() const userId = ref(1) const fetchUser = async () => { const response = await apis.user.getUser(userId.value) userStore.setUser(response.data) } return { userId, fetchUser, } }, }) ``` 以上就是使用 Vite + Vue3 + TypeScript + Pinia + Vue Router + Axios + SCSS 并自动导入 API 的基本设置。你可以根据自己的需求进一步配置和扩展。希望对你有所帮助!
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值