Vue3基础(25)___初尝pinia,相比于vuex轻量、好用

简介: 本文介绍了Pinia在Vue 3中的使用,相比于Vuex,Pinia更轻量且易于使用。文章详细解释了Pinia的基本概念、优势,并提供了安装和使用Pinia的步骤,包括定义状态、getters、actions和如何在组件中使用Pinia进行状态管理。

初尝pinia,相比于vuex轻量、好用

pinia官网入口:pinia官网

Pinia 最初是在 2019 年 11 月左右重新设计使用 Composition API 。从那时起,最初的原则仍然相同,但 Pinia 对 Vue 2 和 Vue 3 都有效,并且不需要您使用组合 API。 除了安装和 SSR 之外,两者的 API 都是相同的,并且这些文档针对 Vue 3,并在必要时提供有关 Vue 2 的注释,以便 Vue 2 和 Vue 3 用户可以阅读

为什么要使用 Pinia?
Pinia 是 Vue 的存储库,它允许您跨组件/页面共享状态。 如果您熟悉 Composition API,您可能会认为您已经可以通过一个简单的 export const state = reactive({}).
这对于单页应用程序来说是正确的,但如果它是服务器端呈现的,会使您的应用程序暴露于安全漏洞。 但即使在小型单页应用程序中,您也可以从使用
Pinia 中获得很多好处:

dev-tools 支持 跟踪动作、突变的时间线 Store 出现在使用它们的组件中 time travel 和 更容易的调试 热模块更换
在不重新加载页面的情况下修改您的 Store 在开发时保持任何现有状态 插件:使用插件扩展 Pinia 功能 为 JS 用户提供适当的
TypeScript 支持或 autocompletion 服务器端渲染支持
与 Vuex 3.x/4.x 的比较
Vuex 3.x 是 Vuex 的 Vue 2 而 Vuex 4.x 是 Vue 3
Pinia API 与 Vuex ≤4 有很大不同,即:
mutations 不再存在。他们经常被认为是 非常 冗长。他们最初带来了 devtools 集成,但这不再是问题。
无需创建自定义复杂包装器来支持 TypeScript,所有内容都是类型化的,并且 API 的设计方式尽可能利用 TS 类型推断。
不再需要注入、导入函数、调用函数、享受自动完成功能!
无需动态添加 Store,默认情况下它们都是动态的,您甚至都不会注意到。请注意,您仍然可以随时手动使用 Store 进行注册,但因为它是自动的,您无需担心。
不再有 modules 的嵌套结构。您仍然可以通过在另一个 Store 中导入和 使用 来隐式嵌套 Store,但 Pinia 通过设计提供平面结构,同时仍然支持 Store 之间的交叉组合方式。 您甚至可以拥有 Store 的循环依赖关系。
没有 命名空间模块。鉴于 Store 的扁平架构,“命名空间” Store 是其定义方式所固有的,您可以说所有 Store 都是命名空间的。

使用:
1.安装 pinia

npm i pinia

2.在main.js中引入根pinia

import {
    createApp } from 'vue'
import App from './App.vue'
import {
    createPinia } from 'pinia'
createApp(App).use(createPinia()).mount('#app')

3.创建单独文件夹存储所有需要的store对象,js、ts文件
在这里插入图片描述

import {
    defineStore } from 'pinia'

export const useHomeStore = defineStore('useHomeStore', {
   
  state() {
   
    return {
   
      name: "六卿",
      age: "18",
      habby: [{
    key: "1", value: "跳舞" }]
    }
  },
  getters: {
   
    getAge(state) {
   
      return Number(state.age) + 10
    }
  },
  actions: {
   
    // 第一个参数就是 调用的时候传入的参数
    changeNewAge(age) {
   
      console.log(this, 'this')
      console.log(age, 'ageageageage')
      this.age = age
    }
  },
})

这样我们就已经创建了一个简单的piniaStore对象,
4.使用:
在这里插入图片描述

<template>
  <div>
    <p style="color: red">Children showTime</p>
    <div class="hello">currentName: {
   {
    name }}</div>
    <div class="hello">currentAge: {
   {
    age }}</div>
    <div class="hello">currentHabby: {
   {
    habby }}</div>
    <button @click="changeNameFun">changeNameFun</button>
  </div>
</template>

<script>
// 需要使用 storeToRefs 将store转化为ref响应式对象
import {
    storeToRefs } from 'pinia';
import {
    useHomeStore } from '../store/home.ts'
export default {
   
  name: 'Children-my',
  setup() {
   
    // 函数 需要调用
    console.log(useHomeStore, 'useHomeStore')
    const storeHome = useHomeStore()
    const {
    name, age, habby } = storeToRefs(storeHome)
    const changeNameFun = () => {
   
      storeHome.name = 'name --- > children ooooo'
    }
    return {
    name, age, habby, changeNameFun }
  },
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.hello {
   
  width: 500px;
  text-align: left;
}
</style>

上面我们用到了一个新的API_____storeToRefs :可以看看官网如何解释
在这里插入图片描述

在这里插入图片描述
解构之后不再具有响应式,需要使用storeToRefs:
为了从 Store 中提取属性同时保持其响应式,您需要使用storeToRefs()。 它将为任何响应式属性创建 refs。 当您仅使用 store 中的状态但不调用任何操作时,这很有用
5.改变store的值
点击 changeNameFun 按钮的时候,执行

    const changeNameFun = () => {
   
      storeHome.name = 'name --- > children ooooo'
    }

会发现页面直接进行了改变,达到了效果,但是想要批量进行改变的时候,可能有些麻烦,我们可以使用$patch进行批量更改:

    const changeAllFun = () => {
   
      // 批量修改数据1
       storeHome.$patch({
   
         name: "batchName",
         age: "222"
       });
       // 批量修改数据2
       storeHome.$patch((state) => {
   
         state.age = 888
         // state.habby.push({ value: 'shoes', key: '3' })
       })
    }

6.使用getter
home.ts

  getters: {
   
    getAge(state) {
   
      return Number(state.age) + 10
    }
  },

页面:

  setup() {
   
    // 函数 需要调用
    console.log(useHomeStore, 'useHomeStore')
    const storeHome = useHomeStore()
    const {
    name, age, habby, getAge } = storeToRefs(storeHome)
    return {
    name, age, habby, getAge}
  },

7.使用actions
home.ts

  actions: {
   
    // 第一个参数就是 调用的时候传入的参数
    changeNewAge(age) {
   
      console.log(this, 'this')
      console.log(age, 'ageageageage')
      this.age = age
    }
  },

页面使用:

  setup() {
   
    // 函数 需要调用
    console.log(useHomeStore, 'useHomeStore')
    const storeHome = useHomeStore()
    const {
    name, age, habby, getAge } = storeToRefs(storeHome)
    const changeAllFun = () => {
   
      storeHome.changeNewAge('9999')
    }
    return {
    name, age, habby, getAge,  changeAllFun }
  },

改变store数据有三种方法
1.store.name
2.store.$patch
3.store.actionsFun
store也有重置方法

store.$reset()

这是知乎的以为大佬的文章,写的着实很详细啊:一文搞懂pinia状态管理(保姆级教程)

全部代码:
页面:
在这里插入图片描述

main.js

import {
    createApp } from 'vue'
import App from './App.vue'
import {
    createPinia } from 'pinia'
createApp(App).use(createPinia()).mount('#app')

app.vue

<template>
  <Bottom />
</template>

<script>
import Bottom from './components/Bottom.vue'

export default {
   
  name: 'App',
  components: {
   
    Bottom,
  }
}
</script>

home.ts

import {
    defineStore } from 'pinia'

export const useHomeStore = defineStore('useHomeStore', {
   
  state() {
   
    return {
   
      name: "六卿",
      age: "18",
      sex:"男",
      habby: [{
    key: "1", value: "跳舞" }]
    }
  },
  getters: {
   
    getAge(state) {
   
      return Number(state.age) + 10
    }
  },
  actions: {
   
    // 第一个参数就是 调用的时候传入的参数
    changeNewAge(age) {
   
      console.log(this, 'this')
      console.log(age, 'ageageageage')
      this.age = age
    }
  },
})

bottom.vue:

<template>
  <div>
    <p style="color: red">Children1 showTime</p>
    <div class="hello">currentName: {
   {
    name }}</div>
    <div class="hello">currentAge: {
   {
    age }}</div>
    <div class="hello">currentSex: {
   {
    sex }}</div>
    <div class="hello">currentHabby: {
   {
    habby }}</div>
    <div class="hello">getAge: {
   {
    getAge }}</div>
    <button @click="changeNameFun">改名称</button>
    <button @click="changeAllFun">changeAllFun</button>
    <button @click="changeResetFun">重置</button>
  </div>
</template>

<script>
// 需要使用 storeToRefs 将store转化为ref响应式对象
import {
    storeToRefs } from 'pinia';
import {
    useHomeStore } from '../store/home.ts'
// import { onMounted, ref, watch } from 'vue'
export default {
   
  name: 'Children1-my',
  setup() {
   
    // 函数 需要调用
    console.log(useHomeStore, 'useHomeStore')
    const storeHome = useHomeStore()
    const {
    name, age, sex, habby, getAge } = storeToRefs(storeHome)
    const changeNameFun = () => {
   
      storeHome.name = 'name --- > children111 ooooo'
    }
    const changeResetFun = () => {
   
      // 将数据重置到最初状态
      storeHome.$reset();
    }
    const changeAllFun = () => {
   
      // sex 被包装成 ref  需要.value支持
      storeHome.sex = sex.value === '男' ? '女' : '男'
      // 批量修改数据
      storeHome.$patch({
   
        habby: "hahahahha"
      });
      // storeHome.$patch((state) => {
   
      //   state.age = 888
      //   // state.habby.push({ value: 'shoes', key: '3' })
      // })
      // 直接替换整个state
      storeHome.$state = {
   
        name: "1233333"
      }
      storeHome.changeNewAge('9999')
    }
    return {
    name, age, sex, habby, getAge, changeNameFun, changeResetFun, changeAllFun }
  },
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.hello {
   
  width: 500px;
  text-align: left;
}
</style>

目录结构:
在这里插入图片描述

目录
相关文章
|
22天前
|
缓存 JavaScript UED
Vue3中v-model在处理自定义组件双向数据绑定时有哪些注意事项?
在使用`v-model`处理自定义组件双向数据绑定时,要仔细考虑各种因素,确保数据的准确传递和更新,同时提供良好的用户体验和代码可维护性。通过合理的设计和注意事项的遵循,能够更好地发挥`v-model`的优势,实现高效的双向数据绑定效果。
126 64
|
22天前
|
JavaScript 前端开发 API
Vue 3 中 v-model 与 Vue 2 中 v-model 的区别是什么?
总的来说,Vue 3 中的 `v-model` 在灵活性、与组合式 API 的结合、对自定义组件的支持等方面都有了明显的提升和改进,使其更适应现代前端开发的需求和趋势。但需要注意的是,在迁移过程中可能需要对一些代码进行调整和适配。
101 60
|
22天前
|
前端开发 JavaScript 测试技术
Vue3中v-model在处理自定义组件双向数据绑定时,如何避免循环引用?
Web 组件化是一种有效的开发方法,可以提高项目的质量、效率和可维护性。在实际项目中,要结合项目的具体情况,合理应用 Web 组件化的理念和技术,实现项目的成功实施和交付。通过不断地探索和实践,将 Web 组件化的优势充分发挥出来,为前端开发领域的发展做出贡献。
28 8
|
21天前
|
存储 JavaScript 数据管理
除了provide/inject,Vue3中还有哪些方式可以避免v-model的循环引用?
需要注意的是,在实际开发中,应根据具体的项目需求和组件结构来选择合适的方式来避免`v-model`的循环引用。同时,要综合考虑代码的可读性、可维护性和性能等因素,以确保系统的稳定和高效运行。
21 1
|
21天前
|
JavaScript
Vue3中使用provide/inject来避免v-model的循环引用
`provide`和`inject`是 Vue 3 中非常有用的特性,在处理一些复杂的组件间通信问题时,可以提供一种灵活的解决方案。通过合理使用它们,可以帮助我们更好地避免`v-model`的循环引用问题,提高代码的质量和可维护性。
32 1
|
22天前
|
JavaScript
在 Vue 3 中,如何使用 v-model 来处理自定义组件的双向数据绑定?
需要注意的是,在实际开发中,根据具体的业务需求和组件设计,可能需要对上述步骤进行适当的调整和优化,以确保双向数据绑定的正确性和稳定性。同时,深入理解 Vue 3 的响应式机制和组件通信原理,将有助于更好地运用 `v-model` 实现自定义组件的双向数据绑定。
|
1月前
|
JavaScript 索引
Vue 3.x 版本中双向数据绑定的底层实现有哪些变化
从Vue 2.x的`Object.defineProperty`到Vue 3.x的`Proxy`,实现了更高效的数据劫持与响应式处理。`Proxy`不仅能够代理整个对象,动态响应属性的增删,还优化了嵌套对象的处理和依赖追踪,减少了不必要的视图更新,提升了性能。同时,Vue 3.x对数组的响应式处理也更加灵活,简化了开发流程。
|
1月前
|
存储 JavaScript
Vue 状态管理工具vuex
Vue 状态管理工具vuex
|
25天前
|
JavaScript 前端开发 API
从Vue 2到Vue 3的演进
从Vue 2到Vue 3的演进
37 0
|
25天前
|
JavaScript 前端开发 API
Vue.js响应式原理深度解析:从Vue 2到Vue 3的演进
Vue.js响应式原理深度解析:从Vue 2到Vue 3的演进
54 0