Vue3 新的发展方向(来源于尤大知乎)

Vue 3 将在 2022 年 2 月 7 日 成为新的默认版本

基于 Vite 的极速构建工具链

<script setup> 带来的开发体验更丝滑的组合式 API 语法

Volar 提供的单文件组件 TypeScript IDE 支持

vue-tsc 提供的针对单文件组件的命令行类型检查和生成

Pinia 提供的更简洁的状态管理

新的开发者工具扩展,同时支持 Vue 2/Vue 3,并且提供一个插件系统来允许社区库自行扩展开发者工具面板。

一、Pinia 简介与基础

1.1 Pinia 简介

  • 官方地址:https://pinia.vuejs.org/
  • Pinia 是 Vuex4 的升级版,也就是 Vuex5
  • Pinia 极大的简化了Vuex的使用,是 Vue3的新的状态管理工具
  • Pinia 对 ts的支持更好,性能更优, 体积更小,无 mutations,可用于 Vue2 和 Vue3
  • Pinia支持Vue Devtools、 模块热更新和服务端渲染

1.2 Pinia 基础

  Vuex 与 Pinia 对比

  • Vuex 中核心部分: State、Getters、Mutations(同步) 和 Actions(异步)
  • Pinia 中核心部分: State、Getters 和 Actions(同步异步均支持)

  Pinia 各部分作用

  • State: 类似于组件中data,用于存储全局状态
  • Getters: 类似于组件中的computed,根据已有的State封装派生数据,也具有缓存的特性
  • Actions: 类似于组件中的methods,用于封装业务逻辑,同步异步均可以

  Pinia 官方示例JS版本

import { defineStore } from 'pinia'

export const todos = defineStore('todos', {
  state: () => ({
    /** @type {{ text: string, id: number, isFinished: boolean }[]} */
    todos: [],
    /** @type {'all' | 'finished' | 'unfinished'} */
    filter: 'all',
    // type will be automatically inferred to number
    nextId: 0,
  }),
  getters: {
    finishedTodos(state) {
      // autocompletion! ✨
      return state.todos.filter((todo) => todo.isFinished)
    },
    unfinishedTodos(state) {
      return state.todos.filter((todo) => !todo.isFinished)
    },
    /**
     * @returns {{ text: string, id: number, isFinished: boolean }[]}
     */
    filteredTodos(state) {
      if (this.filter === 'finished') {
        // call other getters with autocompletion ✨
        return this.finishedTodos
      } else if (this.filter === 'unfinished') {
        return this.unfinishedTodos
      }
      return this.todos
    },
  },
  actions: {
    // any amount of arguments, return a promise or not
    addTodo(text) {
      // you can directly mutate the stat 00e
      this.todos.push({ text, id: this.nextId  , isFinished: false })
    },
  },
})

二、Pinia 在Vue3-Vite中的使用

2.1 基础使用流程

① 创建一个vue vite项目

PS C:\Users\FORGET\Desktop\vue-pinia-demo> npm init vite@latest
Need to install the following packages:
  create-vite@latest
Ok to proceed? (y) y
√ Project name: ... pinia-demo
√ Select a framework: » vue
√ Select a variant: » vue-ts

Scaffolding project in C:\Users\FORGET\Desktop\vue-pinia-demo\pinia-demo...

Done. Now run:

  cd pinia-demo
  npm install
  npm run dev
PS C:\Users\FORGET\Desktop\vue-pinia-demo> cd .\pinia-demo\
PS C:\Users\FORGET\Desktop\vue-pinia-demo\pinia-demo> npm install

② 安装 pinia,-S是为了将其保存至package.json中,便于Git管理给其他人的使用

PS C:\Users\FORGET\Desktop\vue-pinia-demo\pinia-demo> npm install pinia -S

# package.json文件中
 "dependencies": {
    "pinia": "^2.0.9",
    "vue": "^3.2.25"
  },

③ 创建 pinia 实例并挂载到 vue中

// main.ts 文件
import { createApp } from 'vue'
import App from './App.vue'
import {createPinia} from 'pinia'
// 创建 Pinia 实例
const pinia = createPinia()
// 创建 Vue 实例
const app = createApp(App)
// 挂载到 Vue 根实例
app.use(pinia)
app.mount('#app')

④ 在src文件下创建一个store文件夹,并添加index.ts

// store/index.ts
import { defineStore } from 'pinia'
// 1. 定义容器、导出容器
// 参数1:容器的ID,必须是唯一的,后面Pinia会把所有的容器挂载到根容器
// 参数2:一些选项对象,也就是state、getter和action
// 返回值:一个函数,调用即可得到容器实例

export const useMainStore =  defineStore('main',{
    // 类似于Vue2组件中的data,用于存储全局状态数据,但有两个要求
    // 1. 必须是函数,目的是为了在服务端渲染的时候避免交叉请求导致的数据状态污染
    // 2. 必须是箭头函数,这样是为了更好的 TS 类型推导
    state:()=>{
        return {
            info:"pinia 可以使用"
        }
    },
    getters:{},
    actions:{}
})

// 2. 使用容器中的 state
// 3. 通过 getter 修改 state 
// 4. 使用容器中的 action 同步和异步请求

⑤ 在组件中使用

<template>
  <h1>{{ mainStore.info}}</h1>
</template>

<script lang="ts" setup>
import { useMainStore } from "../store";
const mainStore = useMainStore();
</script>

<style>
</style>

2.2 state 中数据的解构访问

状态管理中

// store/index.ts
state:()=>{
        return {
            info:"pinia 可以使用",
            count:10
        }
    },

组件中

<template>
  <h1>{{ mainStore.count }}</h1>
  <h1>{{ mainStore.info }}</h1>
  <hr />
  <h1>{{ count }}</h1>
  <h1>{{ info }}</h1>
  <p>
    <button @click="alertData">修改数据</button>
  </p>
</template>

<script lang="ts" setup>
import { toRefs } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore } from "../store";
const mainStore = useMainStore();
// 解构数据,但是得到的数据是不具有响应式的,只是一次性的
// 相当于仅仅只是...mainStore而已,只是做了reactive处理,并没有做toRefs
// const { count, info } = useMainStore();
// 解决方法:
// 1. 通过使用toRefs函数,因为前面所说相当于是通过reactive处理,因此可以
// const { count, info } = toRefs(mainStore);
// 2. 通过pinia中提供的storeToRefs方法来解决,推荐使用
const { count, info } = storeToRefs(mainStore);
const alertData = () => {
  mainStore.count  = 10
}
</script>

<style>
</style>

2.3 state 中数据的修改方式(actions和组件中)

一般的修改

const alertData = () => {
  // 方式一:最简单的方法,如下
  // 解构后更改方式
  // count.value  = 10
  // 结构前更改方式
  // mainStore.count  = 10
  // 方式二:若要同时修改多个数据,建议使用$patch来实现批量更新,在内部做了优化
  // mainStore.$patch({
  //   count: mainStore.count   1,
  //   info: "hello"
  // })
  // 方式三:更好的批量更新方法,通过$patch传递一个函数来实现,这里的state就是useMainStore容器中的state
  mainStore.$patch(state => {
    state.count  = 10
    state.info = "pinia批量更新"
  })
}

通过actions修改

// store/index.ts
// 类似于vue2组件的methods,用于封装业务逻辑,修改state
// // 注意:不能使用箭头函数来定义actions,因为箭头函数绑定外部的this
    actions:{
        changeState (){
            this.count  = 10
            this.info = "actions修改数据"
        },
        changeStates (num:number){
            this.count  = num   2
            this.info = "actions修改数据"
        }
    }
const alertData = () => {
  // 方式一:最简单的方法,如下
  // 解构后更改方式
  // count.value  = 10
  // 结构前更改方式
  // mainStore.count  = 10
  // 方式二:若要同时修改多个数据,建议使用$patch来实现批量更新,在内部做了优化
  // mainStore.$patch({
  //   count: mainStore.count   1,
  //   info: "hello"
  // })
  // 方式三:更好的批量更新方法,通过$patch传递一个函数来实现,这里的state就是useMainStore容器中的state
  // mainStore.$patch(state => {
  //   state.count  = 10
  //   state.info = "pinia批量更新"
  // })
  // 方式四:通过 actions 来修改数据
  mainStore.changeState()
  mainStore.changeStates(10)
}

2.4 getters 的使用

定义

// 类似于组件的computed,用来封装计算属性,具有缓存的功能
    getters:{
    	 // 函数接收一个可选参数:state状态对象
        count10(state){
            return state.count  = 10
        },
        count10(state){
            return this.count  = 10
        },
        // 若使用this.count,则必须指明返回数据的类型
        count11():number{
            return this.count  = 11
        }
    },

使用

<h1>{{ mainStore.count10 }}</h1>

三、Pinia 数据持久化

保存至localStorage中

import { defineStore } from 'pinia';
const useLoginStore = defineStore({
  id: 'login',
  //   state: () => ({
  //     num: 1,
  //   }),
  state: () => ({
    info: 'pinia 可以使用',
  }),
  getters: {},
  actions: {
    alertInfo() {
      this.info = '可以可以,这个秒';
    },
  },
});

// 数据持久化
// 1. 保存数据
const instance = useLoginStore();
instance.$subscribe((_, state) => {
  localStorage.setItem('login-store', JSON.stringify({ ...state }));
});
// 2. 获取保存的数据,先判断有无,无则用先前的
const old = localStorage.getItem('login-store');
if (old) {
  instance.$state = JSON.parse(old);
}
export default useLoginStore;

使用 插件 pinia-plugin-persist 可以辅助实现数据持久化功能

# 安装插件
pnpm install pinia-plugin-persist --save
// main.ts文件中
import { createPinia } from 'pinia';
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import piniaPluginPersist from 'pinia-plugin-persist';
const pinia = createPinia();
pinia.use(piniaPluginPersist);
const app = createApp(App);
app.use(router);
app.use(pinia);
app.mount('#app');

// 接着在对应的 store 里开启 persist 即可。数据默认存在 sessionStorage 里,并且会以 store 的 id 作为 key。
import { defineStore } from 'pinia';
import piniaPluginPersist from 'pinia-plugin-persist';
const useLoginStore = defineStore({
  id: 'login',
  //   state: () => ({
  //     num: 1,
  //   }),
  state: () => ({
    info: 'pinia 可以使用',
  }),
  // 开启数据缓存
  persist: {
    enabled: true,
  },
  getters: {},
  actions: {
    alertInfo() {
      this.info = '可以可以,这个秒';
    },
  },
});
export default useLoginStore;

其它设置,自定义保存名称,保存位置和需要保存的数据

// 开启数据缓存
  persist: {
    enabled: true,
    strategies: [
      {
        // 自定义名称
        key: 'login_store',
        // 保存位置,默认保存在sessionStorage
        storage: localStorage,
        // 指定要持久化的数据,默认所有 state 都会进行缓存,你可以通过 paths 指定要持久化的字段,其他的则不会进行持久化。
        paths: ['age'],
      },
    ],
  },

总结

到此这篇关于Vue3状态管理之Pinia入门使用的文章就介绍到这了,更多相关Vue3状态管理Pinia使用内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

Vue3状态管理之Pinia的入门使用教程的更多相关文章

  1. vue3获取当前路由地址

    本文详细讲解了vue3获取当前路由地址的方法,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  2. Vue状态管理库Pinia详细介绍

    这篇文章主要介绍了Vue3-pinia状态管理,pinia是 vue3 新的状态管理工具,简单来说相当于之前 vuex,它去掉了 Mutations 但是也是支持 vue2 的,需要的朋友可以参考下

  3. 十分钟带你快速上手Vue3过渡动画

    在开发中我们想要给一个组件的显示和消失添加某种过渡动画,可以很好的增加用户体验,下面这篇文章主要给大家介绍了关于如何快速上手Vue3过渡动画的相关资料,需要的朋友可以参考下

  4. 用vue3封装一个符合思维且简单实用的弹出层

    最近新项目中需要一个弹窗组件,所以我就做了一个,下面这篇文章主要给大家介绍了关于如何利用vue3封装一个符合思维且简单实用的弹出层,文中通过实例代码介绍的非常详细,需要的朋友可以参考下

  5. 使用Vite+Vue3+Vant全家桶快速构建项目步骤详解

    这篇文章主要为大家介绍了使用Vite+Vue3+Vant全家桶快速构建项目步骤详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  6. vue3中$attrs的变化与inheritAttrs的使用详解

    $attrs现在包括class和style属性。 也就是说在vue3中$listeners不存在了,vue2中$listeners是单独存在的,在vue3 $attrs包括class和style属性, vue2中 $attrs 不包含class和style属性,这篇文章主要介绍了vue3中$attrs的变化与inheritAttrs的使用 ,需要的朋友可以参考下

  7. 一文详解Pinia和Vuex与两个Vue状态管理模式

    这篇文章主要介绍了一文详解Pinia和Vuex与两个Vue状态管理模式,Pinia和Vuex一样都是是vue的全局状态管理器。其实Pinia就是Vuex5,只不过为了尊重原作者的贡献就沿用了这个看起来很甜的名字Pinia

  8. vue3中proxy的基本用法说明

    这篇文章主要介绍了vue3中proxy的基本用法说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  9. 如何利用vue3实现一个俄罗斯方块

    俄罗斯方块这个游戏相信大家都玩过,下面这篇文章主要给大家介绍了关于如何利用vue3实现一个俄罗斯方块的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下

  10. Vue3 携手 TypeScript 搭建完整项目结构

    TypeScript 是JS的一个超级,主要提供了类型系统和对ES6的支持,使用 TypeScript 可以增加代码的可读性和可维护性,在 react 和 vue 社区中也越来越多人开始使用TypeScript,这篇文章主要介绍了Vue3 携手 TypeScript 搭建完整项目结构,需要的朋友可以参考下

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部