Vue(Vuex插件)

news2024/11/23 22:32:08

一、Vuex的介绍

1. 概念

专门在Vue中实现集中式状态数据管理的一个Vue插件,对Vue的应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。

2. 了解vuex地址

https://github.com/vuejs/vuexhttps://github.com/vuejs/vuex

3. 图像形式理解vuex

当通过全局事件总线或者消息订阅与发布传递信息时候,给多个组件要一一发送,如果修改又得一一进行修改

  • vuex可以解决一一发送这一弊端

 所以vuex主要使用场景就是:

  • 当多个组件依赖同一个状态
  • 多个不同组件的行为需要变成更同一状态

 4. 通过案例进行理解:

纯vue案例:进行计算

<template>
  <div>
  <h1>当前求和为:{{sum}}</h1>
  <select v-model.number="n">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
  </select>
  <button @click="increment">+</button>
  <button @click="decrement">-</button>
  <button @click="incrementOdd">当前页面为基数+</button>
  <button @click="incrementWait">等一等再+</button>
  </div>
</template>

<script>
export default {
  name:'Count',
  data() {
    return {
      n:1,//用户选择的数字
      sum:0
    }
  },
  methods: {
    increment(){
      this.sum += this.n//注意会拼接字符,
      //是因为没有对option数据进行绑定,绑定之后引号内的就是js表达式
      //使用修饰符对数据进行转换成数值
    },
    decrement(){
       this.sum -= this.n
    },
    incrementOdd(){
      //此处使用取余计算,如果等于0,转换为布尔值就不会进入判断里面
      if(this.sum % 2){
        this.sum  += this.n
      }
    },
    incrementWait(){
      setTimeout(()=>{
        this.sum += this.n
      },500)
    },
  },
 
}
</script>
  • 首先绑定数据
  • 布置页面并设置按钮执行事件
  • 设置执行事件的逻辑
  • 存在问题:绑定数据的时候不是数值
    • 利用:进行绑定value值
    • 或者直接使用修饰符:number

5. Vue工作原理图

 vuex重要组成部分:Actions、Mutations、State

  • State:对象,能保存很多key-value默认值

  • 组件:组件中存在各种方法,调用api-dispatch(‘动作类型’,动作值)

  • Actions:object对象,key和上面动作类型对上,然后调用key所对应的函数,然后自己调用commit(提交)

  • Mutations:object对象,这个对象上面也存在key和上面动作类型对上,然后调用key所对应的函数,函数包含(整个state,动作值)自动进行mutate

  • 然后state就会发生变化,然后重新进行解析

Action,ajax获取到Backend API获取其他服务器上的数据

当Action的值自己知道,那么就直接可以组件执行commit给Mutations

Devtools:直接和mutations对话

简单理解:

组件 === 客人

Action === 服务员

Mutations === 后厨

State === 菜

二、Vuex的使用

1.vuex开发环境搭建

  • 安装vuex:注意vue3成为默认版本,vuex更新到了4版本(在vuex2项目中安装vuex3)

npm i vuex@3
  • 插件的使用:目的是使用vuex之后在vm中存在store配置

    • main中引入vuex

    • 使用vuex,引入和使用在main文件省略(因为会报错)

    • 然后vue实例中配置store

注意:如果没有引入并使用vuex那么就不会在vm或者vc中产生store配置

就算再vm实例中配置很多自定义匹配项但是vm不认就会丢弃

new Vue({
    el:'#app',
    render: h => h(App),
    //store:'hello',//没有引入vux之前再组件中无法找到store
    store,//简写方式:需要在main中引入并使用之后才能配置,然后就会出现在vc和vm中
    },
})
  • 配置store文件:看见store就等于看见vuex的服务员、后厨、菜

    • src中配置store文件
    • 然后在其中创建index.js文件

  • 设置store   :

    • 配置以上三个重要组成部分

    • 然后引入vuex并进行实例化(注意是实例化store)并进行暴露

    • 然后将配置放在实例中(简写方式:key值相等可以简写)

//引入vuex
import Vuex from 'vuex'


//配置actions--用于响应组件中的动作
const actions = {}
//准备mutations--用于操作数据
const mutations = {}
//准备state--用于存储数据
const state = {}



//创建并暴露store
export default  new Vuex.Store({
  actions,
  mutations,
  state,
})
  • 然后在main文件中引入store

// 引入store
// import store from './store/index'后面的文件可以省略(必须是index)
import store  from './store'

报错:Vue.use(vuex)应该在store实例化之前

  •  所以在main中不进行引入vuex和使用(上面提到的报错)

  • 因为引入store时候会自动在使用vuex之前解析出来

  • 直接在store文件中引入vue、vuex,并进行使用vue.use(vuex)

import Vue from 'vue'
//引入vuex
import Vuex from 'vuex'
// 使用插件在创建store之间进行使用vuex
Vue.use(Vuex)

2. vuex写上面计算案例(只用一个组件进行了解vuex工作过程:此处只写加法:进行了解计算方式)减法相同

  • 首先将数据放在state中,然后组件中关于sum的计算就不能执行
  • 组件中设置方法传给actions
increment(){
 // 此处可以不通过actions直接执行mutations获取数据执行方法
     this.$store.dispatch('jia',this.n)
    },
  • actions中配置方法:方法中存在两个参数,分别是上下文和传入的值
  • 并进行上传上下文中的计算方式
 //两个参数:一个是miniStore(context),后面是value
 jia(context, value) {
    console.log(context, value);
    context.commit('JIA',value)
  },
  • 在mutation中进行配置上下下文需要的计算方式
  • mutation中的计算方式应该是大写方式(方便观看)
  • mutation中方法的参数一个是state,一个是传入的value值
JIA(state,value) {
    // console.log(state,value);参数分别是数据监测state中的数据和传入的参数
    state.sum += value
  },
  • 页面读取效果应该从组件中进行获取,直接获取,不需要进行this获取
  • 显示初始值根据vuex中配置进行设置
<h1>当前求和为:{{$store.state.sum}}</h1>

3. 配置奇数加法和等一等计算

  • 组件中直接传入vuex计算方式
 incrementOdd(){
      this.$store.dispatch('jiaOdd',this.n)
     
    },
 incrementWait(){
      this.$store.dispatch('jiaWait',this.n)
    },
  • store文件的actions中配置计算方式:奇数计算和等一等计算
 jiaOdd(context, value) {
    if (context.state.sum % 2) {
      // 上下文直接提交执行动作
      context.commit('JIA', value)
    }
  },
jiaWait(context, value) {
    setTimeout(() => {
      context.commit('JIAN',value)
 },500)
 },
  • mutations中的方法还是 上面配置的方法
const mutations = {
  JIA(state,value) {
    state.sum += value
  },
  JIAN(state,value) {
    state.sum -= value
  }
}

4. 优化vuex匹配流程

可以直接通过mutations中获取到的计算方法:在组件中直接使用commit进行获取

increment(){
   this.$store.commit('JIA',this.n)
},
decrement(){
   this.$store.commit('JIAN',this.n)
}, 

上面的JIA和JIAN都在mutations中存在

5. 开发者工具讲解

 

开发者工具简单理解

  • 直接与mutations进行对话,最后的计算都是通过mutations中的计算

开发者工具中每一步存在的操作

  • 秒表按钮:直接恢复到指定的计算效果
  • 清除效果:直接删除当前的计算效果(删除中间的,所有以来其产生的都会清除)
  • 下载按钮:合并当前点击之前的所有计算步骤,并合并

右上角的三个按钮

  • 红点:不会在捕获计算步骤
  • 清除按钮:清除空所有的操作记录
  • 下载:合并所有步骤

右下角的两个按钮

  • 导出:将计算过程的最终效果复制(存在在剪切板)
  • 导入:直接粘贴在导入框中(Esc退出)

6. vuex中使用的几个问题

为什么需要actions中的context参数

当业务逻辑比较复杂时候,需要先在最外层执行某些事情,然后dispatch某个方法

然后在第二层再处理一点事情,然后调用dispatch

最后一层执行一点事情然后再执行commit

为什么要将简单的计算方式commit给mutations

如果执行奇数计算不用利用commit提交给mutation,可以直接使用state进行计算

context.state.sum += value可以执行但是不规范(开发者工具无法捕获)

为什么将逻辑写在actions而不写在组件方法中

如果执行的动作需要多个服务器进行判断,那么在自身组件写不能实现复用

 7.getters配置项,在store中

不是必须存在,如果要将state默认数据进行一些复杂操作就会体现其作用

  • 参数就是state中的数据,利用返回值进行计算
// 准备getters用于将state中的数据进行直接加工
const getters = {
  // state参数就是state
  bigSum(state) {
    return state.sum * 10
  }
}
  • 配置并暴露
export default  new Vuex.Store({
  actions,
  mutations,
  state,
  getters,
})
  • 模板获取
 <h3>当前求和放大10倍数为:{{$store.getters.bigSum}}</h3>

三、优化vuex的使用

以下内容都是在组建中完成

1. mapState和mapGetters

优化获取数据和优化对数据的复杂操作:粗糙方法

直接使用计算属性获取到sum:来自于当前组件的store的state

模板简单了,但是代码还是冗余

采用一种方式可以获取数据并进行自己命名

mapState:映射数据

  • 首先进行引入
import {mapState} from 'vuex'
  • 计算属性中进行获取(对象和数组方法进行获取)
  • 利用剩余参数进行获取,通过开发者工具最后显示的是vuex的绑定
//借助mapstate从state中获取数据 (对象写法):计算属性名字和获取数据名字不同
...mapState({he:'sum',xuexiao:'school',xueke:'subject'})
//通过数组方式进行获取值(计算属性名字和获取数据名字相同)
 ...mapState(['sum','school','subject']),

mapGetters

  • 首先引入mapGetters
import {mapGetters} from 'vuex'
  • 在计算属性中进行获取
computed:{  
...mapGetters({beishu:'bigSum'}),//对象写法
  ...mapGetters(['bigSum']),//数组写法
}

2. mapMutationsmapActions

mapMutations

  • 首先引入mapMutations
import {mapMutations} from 'vuex'
  • 方法中进行获取:注意会出现问题:获取到的是鼠标事件为没有value
  • 直接在模板中传递数据
  <button @click="increment(n)">+</button>
  <button @click="decrement(n)">-</button>
...mapMutations({increment:'JIA',decrement:'JIAN'}),//对象写法
...mapMutations(['JIA','JIAN']),//数组写法(使用数组引入之后的名就是引入的名字)

mapActions

  • 首先引入mapActions
import {mapActions} from 'vuex'
  • 方法中进行获取:首先利用模板进行传递数据
 <button @click="incrementOdd(n)">当前页面为基数+</button>
 <button @click="incrementWait(n)">等一等再+</button>
  ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'}),//对象形式
  ...mapActions(['jiaOdd','jiaWait']),//数组形式,注意没有生成名字

 以上两个传value值不仅可以通过模板进行获取,还可以通过方法直接进行获取(不使用)

increment(){
  this.接收自定义名字(value值)
}

四、多组件共享数据

创建新的person组件:配置一个不同页面效果

进行配置组件和vuex

  • state数据配置一个对象,在组件中进行遍历获取,计算属性可以直接简化遍历获取源
//store数据编写
 personList: [
    {id: '001',
    name:'张三'}
  ]

//组件中遍历名字
 <ul>
     <li v-for="p in personList" :key='p.id'>{{p.name}}</li>
 </ul>

//获取数据
personList(){
        // 注意获取数据需要使用return进行返回
        return this.$store.state.personList
 },
 // 获取数据
 // ...mapState(['personList'])
  • 配置按钮点击方法:依赖nanoid生成的新的对象并commit
  • 直接在mutations中添加一个方法(给数据添加人)
 add(){
      const personObj =  {id:nanoid(),name:this.name}
      this.$store.commit('ADD_PERSON',personObj)
      this.name = ''
  }

//vuex
 ADD_PERSON(state, value) {
    state.personList.unshift(value)
  }

然后通过上面获取数据的简易方法获取到数据中人数就可以在其他组件中使用 

 

五、vuex模块化

vuex中的不同组件使用的vuex数据和方法都不同:多个不同的vuex内容混合在一块容易混乱

1. 区分组件对象(命名)并配置namespaced配置(开启命名空间)

  • 进行区分:此处只演示person-vuex模块
  • 确定分类:配置项namespaced:true默认值false
  • 通过以上配置组件中获取模块化名字才会被认识
const personOptions = {
  namespaced: true,//此处默认值false
  actions: {
    // 如果包含王:判断0==0 为正确则提交使用mution方法
    addPersonWang(context, value) {
      if (value.name.indexOf('王') === 0) {
        context.commit('ADD_PERSON',value)
      } else {
        alert('添加姓王的人')
      }
    }
  },
  mutations: {
    ADD_PERSON(state, value) {
      state.personList.unshift(value)
    }
  },
  state: {
    personList: [
      {id: '001',
      name:'张三'}
    ]
  },
}

2. 暴露组件模块并配置自定义名字

  • 进行区分之后的store中暴露就不是直接暴露vuex配置:利用modules配置进行区分
  • 注意通过模块化之后进行获取就会出现问题:获取不到数据和actions等
  • 但是组件模块化之后就存在了自定义名字
//创建并暴露store
export default new Vuex.Store({
  // 暴露store的配置:上面配置命名之后以下才会认识
  modules: {
    countAbout: countOptions,
    personAbout:personOptions
  }
})

3. 组件中获取模块化内的数据就需要通过先区分模块再进行引入

  • 然后组件中模板直接获取数据:简易方法需要配合上方的自定义名字
  ...mapState('countAbout',['sum','school','subject','personList']),
  ...mapState('personAbout',['personList']),
computed:{
    ...mapState('countAbout',['sum','school','subject','personList']),
    ...mapState('personAbout',['personList']),
    ...mapGetters('countAbout',['bigSum']),//数组写法
  },
  methods: {
      ...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),//对象写法
   
     ...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'}),//对象形式
      
  },

4. 通过原生方法获取vuex中数据和方法并进行添加时候的代码格式

注意这里使用  /  进行分割

//获取vuex中数据 
computed:{
      personList(){
        // 注意获取数据需要使用return进行返回
        return this.$store.state.personAbout.personList
      },
}
//对模块化vuex中的数据进行获取并执行mutations的方法时候代码格式
 add(){
      const personObj =  {id:nanoid(),name:this.name}
      this.$store.commit('personAbout/ADD_PERSON',personObj)
      this.name = ''
    },

5.通过原生方法获取模块化中的getters

获取数据的时候需要通过【】获取对象数据方法:包裹组件模块暴露的自定义名字

//上面组件中已经配置添加姓王名字
//组件模块中配置getters-获取第一个人名
getters: {
    firstPersonName(state) {
      return state.personList[0].name
    }
  },
//组件中使用
 computed:{
   firstPersonName(){
        // 获取对象方法数组获取
        return this.$store.getters['personAbout/firstPersonName']
      }
  },

6. 优化模块化代码

创建单独的vuex文件:将vuex配置都放在其中并暴露

创建一个总的vuex:

  • 总文件中引入单个的vuex
  • 并暴露
//该文件创建vuex最重要的store
import Vue from 'vue'
//引入vuex
import Vuex from 'vuex'
// 引入store模块
import countOptions from './count'
import personOptions from './person'
// 使用插件在创建store之间进行使用vuex
Vue.use(Vuex)

//创建并暴露store
export default new Vuex.Store({
  // 暴露store的配置:上面配置命名之后以下才会认识
  modules: {
    countAbout: countOptions,
    personAbout:personOptions
  }
})

7.服务器获取人名-对应组件中进行编写

此处使用一个免费api:

https://api.uixsj.cn/hitokoto/get?type=socialicon-default.png?t=N4N7https://api.uixsj.cn/hitokoto/get?type=social

//首先引入nanoid
import { nanoid } from "nanoid"


//actions
 addPersonServe(context) {
      // 发送get请求获取数据
      axios.get('https://api.uixsj.cn/hitokoto/get?type=social').then(
        response => {
          context.commit('ADD_PERSON',{id:nanoid(),name:response.data})
        },
        error => {
          alert(error.message)
        }
      )
    },
//组件中进行设置方法
  <button @click="addPerson">添加一个人,名字随机</button>

//进行获取actions中的方法
 addPerson(){
      this.$store.dispatch('personAbout/addPersonServe')
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/565720.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

BLIP-2:salesforce提出基于冻结视觉编码器和LLM模型参数的高效训练多模态大模型

论文链接&#xff1a;https://arxiv.org/abs/2301.12597 项目代码&#xff1a;https://github.com/salesforce/LAVIS/tree/main/projects/blip2 体验地址&#xff1a;https://huggingface.co/spaces/Salesforce/BLIP2 文档介绍&#xff1a;https://huggingface.co/docs/tran…

浅谈数据中心供配电设计应用以及监控产品选型

摘 要&#xff1a;近年来&#xff0c;随着数据中心的迅猛发展&#xff0c;数据中心的能耗问题也越来越突出&#xff0c;有关数据中心的能源管理和供配电设计已经成为热门问题&#xff0c;合理可靠的数据中心配电系统方案&#xff0c;是提高数据中心电能使用效率&#xff0c;降低…

图片翻译怎么弄?如何把图片翻译成中文?

在使用社交媒体时&#xff0c;可能会遇到来自世界各地的异文化信息&#xff0c;这时我们可以借助图片翻译的方法帮助我们更好地了解这些信息&#xff0c;促进跨文化交流。那么图片翻译怎么弄呢&#xff1f;图片翻译的方法有哪些呢&#xff1f;这篇文章给你推荐三个非常好用的图…

深入理解Java虚拟机:JVM高级特性与最佳实践-总结-11

深入理解Java虚拟机&#xff1a;JVM高级特性与最佳实践-总结-11 Java内存模型与线程概述硬件的效率与一致性Java内存模型主内存与工作内存内存间交互操作 Java内存模型与线程 概述 多任务处理在现代计算机操作系统中几乎已是一项必备的功能了。在许多场景下&#xff0c;让计算…

22WPF----Prism框架

1.关于Prism框架 官网&#xff1a;Prism Library 文档可以参考 源码地址&#xff1a;https://github.com/PrismLibrary/Prism 版本8.1 Prism框架10历史、微软&#xff0c;最新版本使用 2、功能说明 Prism提供了一组设计模式的实现&#xff0c;有助于编写结构良好的且可维…

JavaScript for与forEach结束本轮循环/结束循环

文章目录 前言一、for1.终止当前轮次2.终止循环 二、forEach1.终止当前轮次2.终止循环 总结 前言 我以前一直想尝试一下这个for里嵌switch来着, 找不到合适的机会, 今天写node脚本刚好遇到, 必须狠狠的尝试一下. 一、for 1.终止当前轮次 我先把正确写法放在这里, 如果循环没…

chatgpt赋能python:Python:一个多才多艺的编程语言

Python: 一个多才多艺的编程语言 作为一名有10年 Python 编程经验的工程师&#xff0c;我必须坦言&#xff0c;Python 是我最喜欢的编程语言之一。Python 简单易学&#xff0c;语法简洁&#xff0c;非常适合开发 Web 应用程序、数据分析、人工智能、自然语言处理等方面。 Pyt…

抖音账号矩阵系统源码开发之——视频发布功能开发

视频发布权限在账号矩阵系统研发之初&#xff0c;都是一个备受争议的功能&#xff0c;最早之前我们使用的视频发布权限名字是Video.creat, video.delete权限&#xff0c;但是该权限于2022年10月份做了权限的收回&#xff0c;后又在上架了一个能力叫发布内容至抖音&#xff1a;…

chatgpt赋能Python-python_theano

简介 什么是Python? Python是一种高层次、动态、解释型编程语言。它是一个易于学习且功能强大的语言&#xff0c;拥有广泛的应用领域。Python是由Guido van Rossum于1989年发明和开发的。它的设计哲学强调代码的可读性和简洁性&#xff0c;在保持语言的清晰和简洁性时&#…

chatgpt赋能python:PythonUDF-知道这些你就能轻松实现自己的需求

Python UDF - 知道这些你就能轻松实现自己的需求 如果你是一名Python开发者&#xff0c;你肯定知道Python的强大和适用性。在数据分析、机器学习和Web应用程序等领域&#xff0c;Python的使用已经成为了常态。Python的一个重要特点是拥有大量的库和框架&#xff0c;这些库和框…

C Primer Plus第四章编程练习答案

学完C语言之后&#xff0c;我就去阅读《C Primer Plus》这本经典的C语言书籍&#xff0c;对每一章的编程练习题都做了相关的解答&#xff0c;仅仅代表着我个人的解答思路&#xff0c;如有错误&#xff0c;请各位大佬帮忙点出&#xff01; 1.编写一个程序&#xff0c;提示用户输…

【unity插件】OpenFracture插件实现物体破裂和切割

插件地址 https://github.com/Mustenaka/OpenFracture 使用注意事项 1.如果要导入自定义网格,则必须在导入设置中将“启用读/写”设置为 true。否则,您将收到错误。 2.网格必须是非相交和封闭的。否则,重新三角测量将失败。 上面描绘的是凳子的线框模型。注意横杆如何与…

kotlin协程并发/并行与串行互相切换,CoroutineScope与await

kotlin协程并发/并行与串行互相切换&#xff0c;CoroutineScope与await import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.launch import java.time.LocalTimefun main(args: Arra…

斑梨电子香橙派Orange Pi 5/5B金属N505外壳支持安装风扇双重散热可选带天线和电源

spotpear.cn/index/product/detail/id/1327/no/2574.html detail.tmall.com/item.htm?id719963414095&spma211lz.success.0.0.101d2b902yPJCT 【产品简介】 这是一款专为Orange Pi 5/5B设计的高品质金属外壳,我们将它命名为N505&#xff0c;机箱保留了主板的全部接口&…

简谈变电站综合自动化系统在变电站的应用分析

摘 要&#xff1a;变电站综合自动化系统在变电站的应用主要表现在将电气设备侧的模拟信号转化为数字信号&#xff0c;经转化后的数字信号系统实时处理保存为有用的信息数据&#xff0c;保障数据的完整性和一致性。相较于传统的常规变电站二次系统&#xff0c;变电站综合自动化系…

chatgpt赋能Python-python_pyv8

介绍 Python和JavaScript是web开发中最流行的两种编程语言之一。Python以其简洁、高效、灵活和易读的特性而备受欢迎。而JavaScript则是为了网页和web应用程序而设计的。两种语言各有优点&#xff0c;但在某些情况下&#xff0c;结合使用Python和JavaScript可以实现非常强大的…

操作系统第三章——存储系统(下)

锦衣雪华玉颜色&#xff0c;回眸一笑天下倾 文章目录 3.2.1 虚拟内存的基本概念知识总览传统存储方式的特征&#xff0c;缺点局部性原理虚拟内存的定义如何实现虚拟内存技术知识总结 3.2.2 请求分页管理方式知识总览页表机制缺页中断机制地址变换机制知识回顾 3.2.3 页面置换算…

Fourier分析入门——第8章——Fourier系数的统计描述

目录 第 8章 Fourier系数的统计描述 8.1 引言 8.2 统计假设 8.3 Fourier系数对噪声的均值和方差 8.4 Fourier系数对噪声信号的概率分布 8.5 随机信号的Fourier系数分布 8.6 信号平均 第 8章 Fourier系数的统计描述 8.1 引言 上一章通过假设离散函数是通过对连续函数定期…

chatgpt赋能python:Pythonre.compile:用于优化正则表达式匹配的工具

Python re.compile: 用于优化正则表达式匹配的工具 正则表达式在Python编程中扮演着重要的角色&#xff0c;但在处理复杂的文本数据时&#xff0c;由于其匹配速度较慢&#xff0c;可能影响程序的性能。Python re.compile是一种用于优化正则表达式匹配的强大工具。 什么是Pyth…

chatgpt赋能Python-python_peewee

介绍 Python是一种高效、简洁的编程语言&#xff0c;正因如此&#xff0c;它在世界范围内拥有着广泛的应用。作为一种优秀的Python ORM库&#xff0c;Peewee在实现Python数据库操作的同时&#xff0c;也成为了Python编程人员不可或缺的工具。 Peewee是一个轻量级Python ORM库…