当前位置: 首页 > news >正文

[React] react-hooks如何使用

react-hooks思想和初衷,也是把组件,颗粒化,单元化,形成独立的渲染环境,减少渲染次数,优化性能。

文章目录

      • 1.为什么要使用hooks
      • 2.如何使用hooks
        • 2.1 useState
        • 2.2 useEffect
        • 2.3 useLayoutEffect
        • 2.4 useRef
        • 2.5 useContext
        • 2.6 useReducer
        • 2.7 useMemo
        • 2.8 useCallback
      • 3.总结

1.为什么要使用hooks

  1. react-hooks可以让我们的代码的逻辑性更强,可以抽离公共的方法,公共组件。
  2. react-hooks思想更趋近于函数式编程。用函数声明方式代替class声明方式,虽说class也是es6构造函数语法糖,但是react-hooks写起来更有函数即组件,无疑也提高代码的开发效率(无需像class声明组件那样写声明周期,写生命周期render函数等)
  3. react-hooks可能把庞大的class组件,化整为零成很多小组件,useMemo等方法让组件或者变量制定一个适合自己的独立的渲染空间,一定程度上可以提高性能,减少渲染次数。这里值得一提的是,如果把负责 请求是数据 ➡️ 视图更新的渲染组件,用react-hooks编写的话 ,配合immutable等优秀的开源库,会有更棒的效果(这里特别注意的是⚠️,如果乱用hooks,不但不会提升性能,反而会影响性能,带来各种各样的想不到的问题)。

2.如何使用hooks

  1. useCallback

  2. useContext

  3. useEffect

  4. useLayoutEffect

  5. useMemo

  6. useReducer

  7. useRef

  8. useState

2.1 useState

数据存储,派发更新。

useState出现,使得react无状态组件能够像有状态组件一样,可以拥有自己state,useState的参数可以是一个具体的值,也可以是一个函数用于判断复杂的逻辑,函数返回作为初始值,usestate 返回一个数组,数组第一项用于读取此时的state值 ,第二项为派发数据更新,组件渲染的函数,函数的参数即是需要更新的值。useState和useReduce 作为能够触发组件重新渲染的hooks,我们在使用useState的时候要特别注意的是,useState派发更新函数的执行,就会让整个function组件从头到尾执行一次,所以需要配合useMemo,usecallback等api配合使用。

const DemoState = (props) => {/* number为此时state读取值 ,setNumber为派发更新的函数 */let [number, setNumber] = useState(0) /* 0为初始值 */return (<div><span>{ number }</span><button onClick={ ()=> {setNumber(number+1)console.log(number) /* 这里的number是不能够即使改变的  */} } ></button></div>)
}

state的值是不能即时改变的,只有当下一次上下文执行的时候,state值才随之改变。

2.2 useEffect

useEffect 组件更新副作用钩子。

在function组件中,当组件完成挂载,dom渲染完成,做一些操纵dom,请求数据的时候, useEffect 可以优化性能。

如果我们需要在组件初次渲染的时候请求数据,那么useEffect可以充当class组件中的 componentDidMount。

如果不给useEffect执行加入限定条件,函数组件每一次更新都会触发effect ,那么也就说明每一次state更新,或是props的更新都会触发useEffect执行,此时的effect又充当了componentDidUpdate。

所以说合理的用于useEffect就要给effect加入限定执行的条件,也就是useEffect的第二个参数,这里说是限定条件,也可以说是上一次useeffect更新收集的某些记录数据变化的记忆,在新的一轮更新,useeffect会拿出之前的记忆值和当前值做对比,如果发生了变化就执行新的一轮useEffect的副作用函数,useEffect第二个参数是一个数组,用来收集多个限制条件 。

import React, {useEffect, useState} from 'react';function ClassCmp(props) {const [count, setCount] = useState(0)// didMount, didUpdate// didUpdateuseEffect(() => {console.log(count)document.title = `${count}`/* 定时器 延时器等 */const timer = setInterval(()=>console.log(666),1000)/* 事件监听 */window.addEventListener('resize', handleResize)/* 此函数用于清除副作用 */return function(){clearInterval(timer) window.removeEventListener('resize', handleResize)}}, [count])return (<div><h3>hooks</h3><h3>{count}</h3><button onClick={() => setCount(count + 1)}>add</button><h3>{useClock().toLocaleTimeString()}</h3></div>);
}export default ClassCmp;

如果我们需要在组件销毁的阶段,做一些取消dom监听,清除定时器等操作,那么我们可以在useEffect函数第一个参数,结尾返回一个函数,用于清除这些副作用。相当与componentWillUnmount。

useEffect是不能直接用 async await 语法糖的。用 async effect 可以对effect进行一层包装。

const asyncEffect = (callback, deps)=>{useEffect(()=>{callback()},deps)
}
2.3 useLayoutEffect

渲染更新之前的 useEffect。

useEffect 执行顺序 组件更新挂载完成 -> 浏览器dom 绘制完成 -> 执行useEffect回调 。

useLayoutEffect 执行顺序 组件更新挂载完成 -> 执行useLayoutEffect回调-> 浏览器dom 绘制完成。

useLayoutEffect 代码可能会阻塞浏览器的绘制 如果我们在useEffect 重新请求数据,渲染视图过程中,肯定会造成画面闪动的效果,而如果用useLayoutEffect ,回调函数的代码就会阻塞浏览器绘制,所以可定会引起画面卡顿等效果,那么具体要用 useLayoutEffect 还是 useEffect ,要看实际项目的情况,大部分的情况 useEffect 都可以满足的。

2.4 useRef

useRef: 获取元素 ,缓存数据。

和传统的class组件ref一样,react-hooks 也提供获取元素方法 useRef,它有一个参数可以作为缓存数据的初始值,返回值可以被dom元素ref标记,可以获取被标记的元素节点。

import {useRef} from "react";const DemoUseRef = ()=>{const dom= useRef(null)const handerSubmit = ()=>{/*  <div >表单组件</div>  dom 节点 */console.log(dom.current)}return <div>{/* ref 标记当前dom节点 */}<div ref={dom} >表单组件</div><button onClick={()=>handerSubmit()} >提交</button></div>
}export default DemoUseRef;import {useRef} from "react";const DemoUseRef = ()=>{const dom= useRef(null)const handerSubmit = ()=>{/*  <div >表单组件</div>  dom 节点 */console.log(dom.current)}return <div>{/* ref 标记当前dom节点 */}<div ref={dom} >表单组件</div><button onClick={()=>handerSubmit()} >提交</button></div>
}export default DemoUseRef;

z

useRef还有一个很重要的作用就是缓存数据。

缓存之前的值。

const Counter: React.FC = () => {const [num, setNum] = useState(0)const preNum = useRef()const add = () => {setNum(c => c + 1)preNum.current = num}return (<>{num} - {preNum.current}<button onClick={add}>change</button></>)
}export default Counter;

react-redux 在react-hooks发布后,用react-hooks重新了其中的Provide,connectAdvanced)核心模块,可以见得 react-hooks在限制数据更新,高阶组件上有这一定的优势,其源码大量运用useMemo来做数据判定。

      /* 这里用到的useRef没有一个是绑定在dom元素上的,都是做数据缓存用的 *//* react-redux 用userRef 来缓存 merge之后的 props */const lastChildProps = useRef()//  lastWrapperProps 用 useRef 来存放组件真正的 props信息const lastWrapperProps = useRef(wrapperProps)//是否储存props是否处于正在更新状态const renderIsScheduled = useRef(false)

react-redux中用useRef 对数据做的缓存。

//获取包装的props 
function captureWrapperProps(lastWrapperProps,lastChildProps,renderIsScheduled,wrapperProps,actualChildProps,childPropsFromStoreUpdate,notifyNestedSubs
) {//我们要捕获包装props和子props,以便稍后进行比较lastWrapperProps.current = wrapperProps  //子props lastChildProps.current = actualChildProps //经过  merge props 之后形成的 proprenderIsScheduled.current = false}

react-redux 用重新赋值的方法,改变缓存的数据源,避免不必要的数据更新, 如果选用useState储存数据,必然促使组件重新渲染 所以采用了useRef解决了这个问题。

2.5 useContext

useContext: 自由获取context, 获取父级组件传递过来的context值, 这个当前值就是最近的父级组件 Provider 设置的value值,useContext参数一般是由 createContext 方式引入 ,也可以父级上下文context传递 ( 参数为context )。useContext 可以代替 context.Consumer 来获取Provider中保存的value值。

export const MyContext = React.createContext()function UseContextPage(props) {const ctx = useContext(MyContext)console.log(ctx)return (<div><h3>UseContextPage</h3><h3>{ctx.themeColor}</h3></div>);
}export default UseContextPage;
export const Context = React.createContext()
const DemoContext = ()=> {const value = useContext(Context)/* my name is alien */return <div> my name is { value.name }</div>
}/* 用Context.Consumer 方式 */
const DemoContext1 = ()=>{return <Context.Consumer>{/*  my name is alien  */}{ (value)=> <div> my name is { value.name }</div> }</Context.Consumer>
}export default function UseContext(){return <div><Context.Provider value={{ name:'alien' , age:18 }} ><DemoContext /><DemoContext1 /></Context.Provider></div>
}

在这里插入图片描述

2.6 useReducer

useReducer: 无状态组件中的redux。useReducer 是react-hooks提供的能够在无状态组件中运行的类似redux的功能api, 我们可以通过中间件的方式来增强dispatch redux-thunk redux-sage redux-action redux-promise都是比较不错的中间件。

useReducer 接受的第一个参数是一个函数,我们可以认为它就是一个reducer ,reducer的参数就是常规reducer里面的state和action,返回改变后的state, useReducer第二个参数为state的初始值 返回一个数组,数组的第一项就是更新之后state的值 ,第二个参数是派发更新的dispatch函数 。

dispatch 的触发会触发组件的更新,这里能够促使组件从新的渲染的一个是useState派发更新函数,另一个就 useReducer中的dispatch。

const DemoUseReducer = ()=>{/* number为更新后的state值,  dispatchNumbner 为当前的派发函数 */const [ number , dispatchNumbner ] = useReducer((state,action)=>{const { payload , name  } = action/* return的值为新的state */switch(name){case 'add':return state + 1case 'sub':return state - 1 case 'reset':return payload       }return state},0)return <div>当前值:{ number }{ /* 派发更新 */ }<button onClick={()=>dispatchNumbner({ name:'add' })} >增加</button><button onClick={()=>dispatchNumbner({ name:'sub' })} >减少</button><button onClick={()=>dispatchNumbner({ name:'reset' ,payload:666 })} >赋值</button>{ /* 把dispatch 和 state 传递给子组件  */ }{/*<MyChildren  dispatch={ dispatchNumbner } State={{ number }} /></div>
}

在这里插入图片描述

2.7 useMemo

useMemo: 能形成独立的渲染空间,能够使组件,变量按照约定好规则更新。memo的作用结合了pureComponent纯组件和 componentShouldUpdate功能。会对传进来的props进行一次对比,然后根据第二个函数返回值来进一步判断哪些props需要更新。

function UseMemoPage(props) {const [count, setCount] = useState(0)const [name, setName] = useState("")// 依赖于count改变, 才触发此函数const total = useMemo(() => {console.log("@")let res = 0;for (let i = 0; i < count; i++){res += i}return res}, [count])return (<div><h3>UseMemoPage</h3><h3>{total} - {count}- {name}</h3><button onClick={() => {setCount(count + 1)}}>add</button><input value={name} onChange={event => {setName(event.target.value)}}/></div>);
}export default UseMemoPage;
  1. useMemo可以减少不必要的循环,减少不必要的渲染。
  2. useMemo可以减少子组件的渲染次数。
  3. useMemo让函数在某个依赖项改变的时候才运行, 可以避免不必要的开销。

如果我们应用useMemo根据依赖项合理的颗粒化我们的组件,能起到很棒的优化组件的作用。

2.8 useCallback

useMemo和useCallback接收的参数都是一样,都是在其依赖项发生变化后才执行,都是返回缓存的值,区别在于useMemo返回的是函数运行的结果,useCallback返回的是函数。

这个回调函数是经过处理后的也就是说父组件传递一个函数给子组件的时候,由于是无状态组件每一次都会重新生成新的props函数,这样就使得每一次传递给子组件的函数都发生了变化,这时候就会触发子组件的更新,这些更新是没有必要的,此时我们就可以通过usecallback来处理此函数,然后作为props传递给子组件。

/* 用react.memo */
const DemoChildren = React.memo((props)=>{/* 只有初始化的时候打印了 子组件更新 */console.log('子组件更新')useEffect(()=>{props.getInfo('子组件')},[])return <div>子组件</div>
})const DemoUseCallback=({ id })=>{const [number, setNumber] = useState(1)/* 此时usecallback的第一参数 (sonName)=>{ console.log(sonName) }经过处理赋值给 getInfo */const getInfo  = useCallback((sonName)=>{console.log(sonName)},[id])return <div>{/* 点击按钮触发父组件更新 ,但是子组件没有更新 */}<button onClick={ ()=>setNumber(number+1) } >增加</button><DemoChildren getInfo={getInfo} /></div>
}

useCallback ,必须配合 react.memo pureComponent ,否则不但不会提升性能,还有可能降低性能。

3.总结

react-hooks的诞生,也不是说它能够完全代替class声明的组件,对于业务比较复杂的组件,class组件还是首选,只不过我们可以把class组件内部拆解成funciton组件,根据业务需求,哪些负责逻辑交互,哪些需要动态渲染,然后配合usememo等api,让性能提升起来。react-hooks使用也有一些限制条件,比如说不能放在流程控制语句中,执行上下文也有一定的要求。

相关文章:

[React] react-hooks如何使用

react-hooks思想和初衷&#xff0c;也是把组件&#xff0c;颗粒化&#xff0c;单元化&#xff0c;形成独立的渲染环境&#xff0c;减少渲染次数&#xff0c;优化性能。 文章目录 1.为什么要使用hooks2.如何使用hooks2.1 useState2.2 useEffect2.3 useLayoutEffect2.4 useRef2.5…...

多个pdf合并成一个文件,3个方法合并pdf

如何把多个pdf合并成一个文件&#xff1f;在我们日常的工作中&#xff0c;经常会遇到一些需要处理的文件&#xff0c;其中包括PDF文件。特别是当我们需要将多个PDF文件合并成一个PDF文件时&#xff0c;会面临一些困难。这样的情况下&#xff0c;我们的阅读能力会受到限制&#…...

代码随想录 动态规划Ⅸ

198. 打家劫舍 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&#xff0c;系统会自动报警。 给定一个代表每个…...

【数据结构】散列表(哈希表)的学习知识总结

目录 1、散列表 2、散列函数 2.1 定义 2.2 散列函数的构造 2.2.1 除留余数法 2.2.2 直接定址法 2.2.3 数字分析法 2.2.4 平方取中法 3、冲突&#xff08;碰撞&#xff09; 4、处理冲突的方法 4.1 拉链法&#xff08;链接法&#xff09; 4.2 开放定址法 5、C语言…...

2023智慧云打印小程序源码多店铺开源版 +前端

智慧自助云打印系统/智慧云打印小程序源码 前端 这是一款全新的基于Thinkphp的最新自助打印系统&#xff0c;最新UI界面设计的云打印小程序源码...

利用亚马逊 云服务器 EC2 和S3免费套餐搭建私人网盘

网盘是一种在线存储服务&#xff0c;提供文件存储&#xff0c;访问&#xff0c;备份&#xff0c;贡献等功能&#xff0c;是我们日常中不可或缺的一种服务。很多互联网公司都为个人和企业提供免费的网盘服务。但这些免费服务都有一些限制&#xff0c;比如限制下载速度&#xff0…...

数据分析技能点-数据的种类

在日常生活中,数据无处不在。当你去超市购物时,你可能会注意到商品的价格、重量、口味等;当你在社交媒体上浏览时,你可能会注意到好友的点赞数、评论等。这些都是数据的一种形式,而了解这些数据的种类和特点有助于我们更好地理解和使用它们。 数据的基本分类 数据大致可…...

解读:ISO 14644-21:2023《洁净室及相关受控环境:悬浮粒子采样》发布指导粒子采样!

药品洁净实验室环境监测结果是否满足微生物检测需求&#xff0c;直接决定检测结果的有效性准确性&#xff0c;进行药品微生物检测&#xff0c;必须对实验环境进行日常和定期监测&#xff0c;其内容包括非生物活性的空气悬浮粒子数及有生物活性的微生物监测。 悬浮粒子监测是保证…...

Java --- MySQL8之索引优化与查询优化

目录 一、索引失效场景 1.1、全值匹配 1.2、最佳左前缀规则 1.3、主键插入顺序 1.4、计算、函数、类型转换(自动或手动)导致索引失效 1.5、类型转换导致索引失效 1.6、范围条件右边的列索引失效 1.7、不等于(! 或者<>)索引失效 1.8、is null可以使用索引&…...

澳大利亚新版《2023年消费品(36个月以下儿童玩具) 安全标准》发布 旨在降低危险小零件的伤害

2023年9月4日&#xff0c;澳大利亚政府发布了新的儿童玩具强制性安全标准《2023年消费品(36个月以下儿童玩具)安全标准》&#xff08;Consumer Goods (Toys for Children up to and including 36 Months of Age) Safety Standard 2023&#xff09;。该强制性标准旨在尽可能地降…...

表格内日期比较计算

需求&#xff1a;在表格中新增数据&#xff0c;计算开始日期中最早的和结束日期中最晚的&#xff0c;回显到下方。 <el-formref"formRef":model"ruleForm":rules"rules"style"margin-top: 20px;"label-position"top">…...

Linux内核启动流程-第二阶段start_kernel 函数

一. Linux内核启动 上一篇文章简单介绍了 Linux内核启动的第一阶段&#xff0c;即执行汇编流程。 本文简单了解一下&#xff0c;Linux内核启动的第二阶段&#xff1a;start_kernel函数&#xff0c;这是一个 C 函数。 本文续上一篇文章的学习&#xff0c;地址如下&#xff1a;…...

Disruptor:无锁队列设计的背后原理

简介 在高并发场景下&#xff0c;队列的速度和效率是关键。而Disruptor&#xff0c;一种高性能的并发队列&#xff0c;通过独特的设计&#xff0c;解决了传统队列在处理高并发时可能遇到的性能瓶颈。本文将深入分析Disruptor如何通过环形数组结构、元素位置定位以及无锁设计&a…...

网络编程-UDP协议(发送数据和接收数据)

需要了解TCP协议的&#xff0c;可以看往期文章 https://blog.csdn.net/weixin_43860634/article/details/133274701 TCP/IP参考模型 通过此图&#xff0c;可以了解UDP所在哪一层级中 代码案例 发送数据 package com.hidata.devops.paas.udp;import java.io.IOException; …...

AI绘画普及课【一】绘画入门

文章目录 一、AI 绘画入门1、Stable Diffusion VS. MidJourney2、Stable Diffusion 介绍3、Stable Diffusion 环境搭建4、文生图与图生图 一、AI 绘画入门 1、Stable Diffusion VS. MidJourney Midjourney 优点: 操作简单、出图绚丽多彩 缺点: 订阅付费充钱 内容有限制&a…...

Selenium和Requests搭配使用

Selenium和Requests搭配使用 前要1. CDP2. 通过requests控制浏览器2. 1 代码一2. 2 代码2 3. 通过selenium获取cookie, requests携带cookie请求 前要 之前有提过, 用selenium控制本地浏览器, 提高拟人化,但是效率比较低,今天说一种selenium和requests搭配使用的方法 注意: 一定…...

【JDK 8-函数式编程】4.4 Supplier

一、Supplier 接口 二、实战 Stage 1: 创建 Student 类 Stage 2: 创建方法 Stage 3: 调用方法 Stage 4: 执行结果 一、Supplier 接口 供给型 接口: 无入参&#xff0c;有返回值&#xff08;T : 出参类型&#xff09; 调用方法: T get(); 用途: 如 无参的工厂方法&#x…...

后端大厂面试-16道面试题

1 java集合类有哪些&#xff1f; List是有序的Collection&#xff0c;使用此接口能够精确的控制每个元素的插入位置&#xff0c;用户能根据索引访问List中元素。常用的实现List的类有LinkedList&#xff0c;ArrayList&#xff0c;Vector&#xff0c;Stack。 ArrayList是容量…...

产品经理认证(UCPM)备考心得

UCPM是联合国训练所CIFAL中心颁发的产品经理证书。如今&#xff0c;ESG是推动企业可持续发展的新潮流。UCPM作为一种可持续发展证书&#xff0c;为我们带来了一套先进科学、系统全面的产品管理模式&#xff0c;是产品管理领域公认的权威证书。那么&#xff0c;如何准备这张证书…...

E : A DS顺序表_删除有序表中的重复元素

Description 给定一个按升序排列的顺序表&#xff0c;请删除所有重复的元素&#xff0c;使得每个元素只出现一次&#xff0c;并输出处理后的顺序表。 Input 第一行输入t&#xff0c;表示有t个测试样例。 第二行起&#xff0c;每一行首先输入n&#xff0c;表示有n个元素&…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

Ascend NPU上适配Step-Audio模型

1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统&#xff0c;支持多语言对话&#xff08;如 中文&#xff0c;英文&#xff0c;日语&#xff09;&#xff0c;语音情感&#xff08;如 开心&#xff0c;悲伤&#xff09;&#x…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配

目录 一、C 内存的基本概念​ 1.1 内存的物理与逻辑结构​ 1.2 C 程序的内存区域划分​ 二、栈内存分配​ 2.1 栈内存的特点​ 2.2 栈内存分配示例​ 三、堆内存分配​ 3.1 new和delete操作符​ 4.2 内存泄漏与悬空指针问题​ 4.3 new和delete的重载​ 四、智能指针…...

Python网页自动化Selenium中文文档

1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API&#xff0c;让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API&#xff0c;你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...

Python 高级应用10:在python 大型项目中 FastAPI 和 Django 的相互配合

无论是python&#xff0c;或者java 的大型项目中&#xff0c;都会涉及到 自身平台微服务之间的相互调用&#xff0c;以及和第三发平台的 接口对接&#xff0c;那在python 中是怎么实现的呢&#xff1f; 在 Python Web 开发中&#xff0c;FastAPI 和 Django 是两个重要但定位不…...

电脑桌面太单调,用Python写一个桌面小宠物应用。

下面是一个使用Python创建的简单桌面小宠物应用。这个小宠物会在桌面上游荡&#xff0c;可以响应鼠标点击&#xff0c;并且有简单的动画效果。 import tkinter as tk import random import time from PIL import Image, ImageTk import os import sysclass DesktopPet:def __i…...