【react全家桶】react-Hook (下)

本人大二学生一枚,热爱前端,欢迎来交流学习哦,一起来学习吧。
<专栏推荐>
🔥:js专栏

🔥:vue专栏

🔥:react专栏

文章目录

  • 15【react-Hook (下)】
    • 1.React.memo
      • 1.1 基本介绍
      • 1.2 问题的引出
      • 1.3 使用React.memo
      • 1.4 使用注意
      • 1.5 容易出错的情况
    • 2.useCallback
      • 2.1 基本介绍
      • 2.2 解决1.5遗留的问题
      • 2.3 第二个参数的使用
    • 3.useMemo
      • 3.1 问题的引出
      • 3.2 使用 useMemo 解决上面的问题
      • 3.3 第二个参数的使用
    • 4.React.forwardRef
    • 5.useImperativeHandle

15【react-Hook (下)】

1.React.memo

1.1 基本介绍

这是一个高阶组件,用来做性能优化的,这个本来应该是写在React高级指引中的,但是这个案例会和后面的useCallback联合起来,所以就写在这里了

  • React.memo() 是一个高阶组件,如果你的组件在相同 props 的情况下渲染相同的结果,那么你可以通过将其包装在 React.memo 中调用,以此通过记忆组件渲染结果的方式来提高组件的性能表现。
    • 它接收另一个组件作为参数,并且会返回一个包装过的新组件
    • 包装过的新组件就会具有缓存功能,这意味着在这种情况下,React 将跳过渲染组件的操作并直接复用最近一次渲染的结果。
    • 包装过后,只有组件的props发生变化,才会触发组件的重新的渲染,否则总是返回缓存中结果。如果函数组件被 React.memo 包裹,且其实现中拥有 useStateuseReduceruseContext 的 Hook,当 state 或 context 发生变化时,它仍会重新渲染。

1.2 问题的引出

React组件会在两种情况下发生重新渲染。第一种,当组件自身的state发生变化时。第二种,当组件的父组件重新渲染时。第一种情况下的重新渲染无可厚非,state都变了,组件自然应该重新进行渲染。但是第二种情况似乎并不是总那么的必要。

App.jsx

import React, { useState } from 'react'

export default function App() {
  console.log('App渲染')

  const [count, setCount] = useState(1)

  const clickHandler = () => {
    setCount(prevState => prevState + 1)
  }

  return (
    <div>
      <h2>App -- {count}</h2>
      <button onClick={clickHandler}>增加</button>
      <A />
    </div>
  )
}

function A() {
  console.log('A渲染')
  return <div>我是A组件</div>
}

在点击增加后,我们发现AppA都重新渲染了。

当APP组件重新渲染时,A组件也会重新渲染。A组件中没有state,甚至连props都没有设置。换言之,A组件无论如何渲染,每次渲染的结果都是相同的,虽然重渲染并不会应用到真实DOM上,但很显然这种渲染是完全没有必要的。

image-20221030172720453

为了减少像A组件这样组件的渲染,React为我们提供了一个方法React.memo()。该方法是一个高阶函数,可以用来根据组件的props对组件进行缓存,当一个组件的父组件发生重新渲染,而子组件的props没有发生变化时,它会直接将缓存中的组件渲染结果返回而不是再次触发子组件的重新渲染,这样一来就大大的降低了子组件重新渲染的次数。

1.3 使用React.memo

使用React.memo包裹A组件

这里只是为了演示方便,把所有组件写一个文件,就用这种方式包裹A组件,平时单文件组件的时候我们这样使用,export default React.memo(A)

import React, { useState } from 'react'

export default function App() {
  console.log('App渲染')

  const [count, setCount] = useState(1)

  const clickHandler = () => {
    setCount(prevState => prevState + 1)
  }

  return (
    <div>
      <h2>App -- {count}</h2>
      <button onClick={clickHandler}>增加</button>
      <A />
    </div>
  )
}

const A = React.memo(() => {
  console.log('A渲染')
  return <div>我是A组件</div>
})

修改后的代码中,并没有直接使用A组件,而是在A组件外层套了一层函数React.memo(),这样一来,返回的A组件就增加了缓存功能,只有当A组件的props属性发生变化时,才会触发组件的重新渲染。memo只会根据props判断是否需要重新渲染,和state和context无关,state或context发生变化时,组件依然会正常的进行重新渲染

在点击增加后,我们发现只有App重新渲染了。

image-20221030173239606

这时我们改下代码

export default function App() {
  console.log('App渲染')

  const [count, setCount] = useState(1)

  const clickHandler = () => {
    setCount(prevState => prevState + 1)
  }
	
  // 增加
  const test = count % 4 === 0

  return (
    <div>
      <h2>App -- {count}</h2>
      <button onClick={clickHandler}>增加</button>
  	  {/* 改动 */}
      <A test={test} />
    </div>
  )
}

const A = React.memo(props => {
  console.log('A渲染')
  return (
    <div>
      我是A组件
      {/* 增加 */}
      <p>{props.test && 'props.test 为 true'}</p>
    </div>
  )
})

这次加了个表达式的结果传给A组件,一开始是false,只有为true的时候,A组件才会重新渲染

这时界面是这样的

image-20221030174105525

点击3次后,表达式为true,A组件的props发生改变,所以重新渲染了。

image-20221030173754653

1.4 使用注意

  1. 此方法仅作为**性能优化**的方式而存在。但请不要依赖它来“阻止”渲染,因为这会产生 bug。
  2. 与 class 组件中 shouldComponentUpdate() 方法不同的是,如果 props 相等,areEqual 会返回 true;如果 props 不相等,则返回 false。这与 shouldComponentUpdate 方法的返回值相反。

1.5 容易出错的情况

先回到这个案例的初始代码,在这之上进行修改

我们把App组件clickHandler方法传递给A组件,让A组件也能够改变App组件state

import React, { useState } from 'react'

export default function App() {
  console.log('App渲染')

  const [count, setCount] = useState(1)

  const clickHandler = () => {
    setCount(prevState => prevState + 1)
  }

  return (
    <div>
      <h2>App -- {count}</h2>
      <button onClick={clickHandler}>增加</button>
      <A clickHandler={clickHandler} />
    </div>
  )
}

const A = React.memo(props => {
  console.log('A渲染')
  return (
    <div>
      我是A组件
      <button onClick={props.clickHandler}>A组件的增加</button>
    </div>
  )
})

点击A组件的增加,发现A组件也重新渲染了

image-20221030175830062

这是因为App组件重新渲染的时候,clickHandler也重新创建了,这时传递给子组件的clickHandler和上一次不一样,所以react.memo失效了。

这个问题可以用useCallback解决。

2.useCallback

2.1 基本介绍

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);

把内联回调函数及依赖项数组作为参数传入 useCallback,它将返回该回调函数的 memoized 版本,该回调函数仅在某个依赖项改变时才会更新。当你把回调函数传递给经过优化的并使用引用相等性去避免非必要渲染(例如 shouldComponentUpdate)的子组件时,它将非常有用。

useCallbackuseMemo设计的初衷是用来做性能优化的。在Class Component中考虑以下的场景:

class Foo extends Component {
  handleClick() {
    console.log('Click happened');
  }
  render() {
    return <Button onClick={() => this.handleClick()}>Click Me</Button>;
  }
}

传给 Button 的 onClick 方法每次都是重新创建的,这会导致每次 Foo render 的时候,Button 也跟着 render。优化方法有 2 种,箭头函数和 bind。下面以 bind 为例子:

class Foo extends Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick() {
    console.log('Click happened');
  }
  render() {
    return <Button onClick={this.handleClick}>Click Me</Button>;
  }
}

同样的,Function Component也有这个问题:

function Foo() {
  const [count, setCount] = useState(0);

  const handleClick() {
    console.log(`Click happened with dependency: ${count}`)
  }
  return <Button onClick={handleClick}>Click Me</Button>;
}

而 React 给出的方案是useCallback Hook。在依赖不变的情况下 (在我们的例子中是 count ),它会返回相同的引用,避免子组件进行无意义的重复渲染

2.2 解决1.5遗留的问题

/*
*   useCallback()
*		这个hook会缓存方法的引用
*       参数:
*           1. 回调函数
*           2. 依赖数组
*               - 当依赖数组中的变量发生变化时,回调函数才会重新创建
*               - 如果不指定依赖数组,回调函数每次都会重新创建
*               - 一定要将回调函数中使用到的所有变量都设置到依赖数组中
*                   除了(setState)
* */

我们将clickHandler方法改造一下

  const clickHandler = useCallback(() => {
    setCount(prevState => prevState + 1)
  }, [])

第二个参数一定要加,不然和平常写没有区别

依赖项[]的意思是只有第一次渲染时才会创建,之后都不会重新创建了

点击A组件的增加,发现只有App组件重新渲染了。因为clickHandler没有重新创建,传给子组件的没有变化,所以子组件这次没有重新渲染。

image-20221030180349406

完整代码

import React, { useState, useCallback } from 'react'

export default function App() {
  console.log('App渲染')

  const [count, setCount] = useState(1)

  const clickHandler = useCallback(() => {
    setCount(prevState => prevState + 1)
  }, [])

  return (
    <div>
      <h2>App -- {count}</h2>
      <button onClick={clickHandler}>增加</button>
      <A clickHandler={clickHandler} />
    </div>
  )
}

const A = React.memo(props => {
  console.log('A渲染')
  return (
    <div>
      我是A组件
      <button onClick={props.clickHandler}>A组件的增加</button>
    </div>
  )
})

2.3 第二个参数的使用

继续改造上面的代码

import React, { useState, useCallback } from 'react'

export default function App() {
  console.log('App渲染')

  const [count, setCount] = useState(1)
  // 增加
  const [num, setNum] = useState(1)

  const clickHandler = useCallback(() => {
    setCount(prevState => prevState + num)
  // 增加
    setNum(prevState => prevState + 1)
  }, [])

  return (
    <div>
      <h2>App -- {count}</h2>
      <button onClick={clickHandler}>增加</button>
      <A clickHandler={clickHandler} />
    </div>
  )
}

const A = React.memo(props => {
  console.log('A渲染')
  return (
    <div>
      我是A组件
      <button onClick={props.clickHandler}>A组件的增加</button>
    </div>
  )
})

增加了一个num,让每一次count的增加比上次多1,现在这样写是有问题的。

image-20221030181249832

点击了两次增加后,预期值应该是4,但是显示的是3,是为什么呢?

因为clickHandler只在初次渲染的时候创建,当时num的值是1,这个函数一直没有重新创建,内部用的num一直是1

这时我们可以加一个依赖项

const clickHandler = useCallback(() => {
    setCount(prevState => prevState + num)
    setNum(prevState => prevState + 1)
  }, [num])

这样num变化了,这个函数也会重新创建。

image-20221030181534667

点击了两次增加后,count变成了预期值4。

3.useMemo

useMemo和useCallback十分相似,useCallback用来缓存函数对象,useMemo用来缓存函数的执行结果。在组件中,会有一些函数具有十分的复杂的逻辑,执行速度比较慢。闭了避免这些执行速度慢的函数返回执行,可以通过useMemo来缓存它们的执行结果,像是这样:

const result = useMemo(()=>{
    return 复杂逻辑函数();
},[依赖项])

useMemo中的函数会在依赖项发生变化时执行,注意!是执行,这点和useCallback不同,useCallback是创建。执行后返回执行结果,如果依赖项不发生变化,则一直会返回上次的结果,不会再执行函数。这样一来就避免复杂逻辑的重复执行。

3.1 问题的引出

App.jsx

import React, { useMemo, useState } from 'react'

const App = () => {
  const [count, setCount] = useState(1)

  let a = 123
  let b = 456

  function sum(a, b) {
    console.log('sum执行了')
    return a + b
  }
    
  return (
    <div>
      <h1>App</h1>
      <p>sum的结果:{sum(a, b)}</p>
      <h3>{count}</h3>
      <button onClick={() => setCount(prevState => prevState + 1)}>点我</button>
    </div>
  )
}

export default App

这是一个计数器案例,但是多添加了一个函数展示结果,这种情况这个函数只需要在一开始调用一次就够了,但是count的改变会导致重新渲染模板,这样sum函数也会反复执行。

image-20221107143139632

现在这个sum函数太简单了,体现不出性能上的问题,我们可以把sum中的逻辑改复杂一点。

import React, { useMemo, useState } from 'react'

const App = () => {
  const [count, setCount] = useState(1)

  let a = 123
  let b = 456

  function sum(a, b) {
    console.log('sum执行了')
    const begin = +new Date()
    while (true) {
      if (Date.now() - begin > 3000) break
    }
    return a + b
  }
  return (
    <div>
      <h1>App</h1>
      <p>sum的结果:{sum(a, b)}</p>
      <h3>{count}</h3>
      <button onClick={() => setCount(prevState => prevState + 1)}>点我</button>
    </div>
  )
}

export default App

增加了一个功能,让这个函数起码3秒才能执行完。

image-20221107143451560

这个时候因为sum函数要3秒才能执行完,导致下面数字显示也变慢了3秒。

3.2 使用 useMemo 解决上面的问题

App.jsx

改写模板中的sum方法的调用

<p>sum的结果:{useMemo(() => sum(a, b), [])}</p>

image-20221107143946116

第一次加载慢是不可避免的,但是这个钩子函数将sum函数的返回值缓存起来,这样我们模板重新渲染时就没有再去执行sum函数,而是直接使用上一次的返回值。

3.3 第二个参数的使用

继续改造上面的代码,把Sum单独抽离成一个组件

Sum.jsx

import React from 'react'

export default function Sum(props) {
  console.log('Sum执行了')
  return <span>{props.a + props.b}</span>
}

App.jsx

添加了一个功能可以变换a的值

import React, { useMemo, useState } from 'react'
import Sum from './Sum'

const App = () => {
  const [count, setCount] = useState(1)

  let a = 123
  let b = 456

  if (count % 2 === 0) a = a + 1

  const result = useMemo(() => <Sum a={a} b={b} />, [])

  return (
    <div>
      <h1>App</h1>
      <p>sum的结果:{result}</p>
      <h3>{count}</h3>
      <button onClick={() => setCount(prevState => prevState + 1)}>点我</button>
    </div>
  )
}

export default App

现在有一个问题,如果Sum组件接收的值变化了,网页上显示的还是原来的缓存值,这个时候就要利用第二个参数。

image-20221107145159066

App.jsx

const result = useMemo(() => <Sum a={a} b={b} />, [a])

这里的意思和以前是一样的,如果a的值变化了,将会重新计算。

image-20221107145403725

4.React.forwardRef

这是一个高阶组件,用来做性能优化的,这个本来应该是写在React高级指引中的,但是这个案例会和后面的useImperativeHandle联合起来,所以就写在这里了

React.forwardRef 会创建一个React组件,这个组件能够将其接受的 ref 属性转发到其组件树下的另一个组件中。这种技术并不常见,但在以下两种场景中特别有用:

  • 转发 refs 到 DOM 组件
  • 在高阶组件中转发 refs

React.forwardRef 接受渲染函数作为参数。React 将使用 propsref 作为参数来调用此函数。此函数应返回 React 节点。

import React, { useRef } from 'react'

const Child = React.forwardRef((props, ref) => {
  return (
    <>
      <h2>这是Child组件</h2>
      <input type="text" ref={ref} />
    </>
  )
})

export default function App() {
  const childRef = useRef(null)
  console.log(childRef)
  return (
    <div>
      <h2>这是App组件</h2>
      <Child ref={childRef} />
    </div>
  )
}

在上述的示例中,React 会将 <Child ref={childRef}> 元素的 ref 作为第二个参数传递给 React.forwardRef 函数中的渲染函数。该渲染函数会将 ref 传递给 <input ref={ref}> 元素。

因此,当 React 附加了 ref 属性之后,ref.current 将直接指向 <input> DOM 元素实例。

image-20221107150428406

我们改造App组件

export default function App() {
  const childRef = useRef(null)

  childRef.current.value = 'App组件设置的'

  return (
    <div>
      <h2>这是App组件</h2>
      <Child ref={childRef} />
    </div>
  )
}

image-20221107150535398

我们可以直接在App组件操作Child组件的内容,但是这样并不好,我们希望Child组件的内容只由Child组件自己去操作,所以引出了useImperativeHandle

5.useImperativeHandle

useImperativeHandle(ref, createHandle, [deps])

useImperativeHandle 可以让你在使用 ref 时自定义暴露给父组件的实例值。在大多数情况下,应当避免使用 ref 这样的命令式代码。useImperativeHandle 应当与 forwardRef 一起使用:

App.jsx

import React, { useRef, useEffect, useImperativeHandle } from 'react'

const Child = React.forwardRef((props, ref) => {
  const inputRef = useRef(null)

  const changeInputValue = value => (inputRef.current.value = value)

  // useImperativeHandle 可以用来指定ref返回的值
  useImperativeHandle(ref, () => ({
    changeInputValue,
  }))

  return (
    <>
      <h2>这是Child组件</h2>
      <input type="text" ref={inputRef} />
    </>
  )
})

export default function App() {
  const childRef = useRef(null)

  useEffect(() => {
    console.log(childRef)
  }, [])

  return (
    <div>
      <h2>这是App组件</h2>
      <button onClick={() => childRef.current.changeInputValue('App组件修改的')}>点击改变</button>
      <Child ref={childRef} />
    </div>
  )
}

我们来看看childRef的输出是什么

image-20221107151926890

可以发现我们把子组件的changeInputValue暴露出去了。

image-20221107152122394

点击按钮发现也是可以正常使用的。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

普源1G带宽4通道10G采样率数字示波器MSO8104

超高性价比七合一 集成示波器在如今的集成设计领域&#xff0c;一款集成度较高的综合示波器已经成为设计工程师必不可少的得力工具。 MSO8000 系列数字示波器&#xff0c;它集 7 种独立仪器于一体&#xff0c;包括一台示波器、一台 16 通道逻辑分析仪、一台频谱分析仪、一台任…

ipad触控笔是哪几款?一般电容笔和Apple pencil区别

和苹果Pencil最大的区别就是&#xff0c;电容笔没具备重力压感&#xff0c;只有一种倾斜的压感。如果你不经常画画&#xff0c;那么你可以使用一款平替电容笔。这种平替电容笔&#xff0c;不仅仅是用在办公上&#xff0c;还能用来做笔记和练习。更何况&#xff0c;现在苹果一款…

【密码学复习】第十章 身份鉴别

身份鉴别的定义 定义&#xff1a;身份鉴别&#xff0c;又称为身份识别、身份认证。它是证实客户的真实身份与其所声称的身份是否相符的过程。 口令身份鉴别 固定口令&#xff08;四&#xff09; 注册环节&#xff1a;双因子认证 ① 接收用户提供的口令pw&#xff08;PIN&…

JVM-基础知识

JVM基础知识 JVM结构图 字节码文件 Java虚拟机不和包括Java在内的任何语言绑定,它只与字节码文件这种特定的二进制文件格式所关联. Class文件结构不仅仅是JVM的执行入口,更是Java生态圈的基础和核心. 字节码文件内容是什么 字节码是一种二进制的类文件,他的内容是JVM指令,而…

github在线编程

github在线编程 文章目录 github在线编程两种区别演示项目 Ruoyi-VueGitHub Codespaces 演示github 访问项目使用 GitHubCodeSpace 打开该项目查看运行环境安装运行环境初始化myql数据安装 redis运行前端运行后端前后端运行成功测试安装相关插件 GitPod 演示 说明: 目前总结 gi…

把玩数据在内存中的存储

前言&#xff1a;时光如梭&#x1f4a6;&#xff0c;今天到了C语言进阶啦&#x1f60e;&#xff0c;基础知识我们已经有了初步认识&#xff0c; 是时候该拔高拔高自己了&#x1f63c;。 目标&#xff1a;掌握浮点数在内存的存储&#xff0c;整形在内存的存储。 鸡汤&#xff1a…

好玩!AI文字RPG游戏;播客进入全AI时代?LangChain项目实践手册;OpenAI联创科普GPT | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f916; Microsoft Build 中国黑客松挑战赛&#xff0c;进入AI新纪元 近期&#xff0c;伴随着人工智能的新一轮浪潮&#xff0c;Hackathon (黑…

【网络协议详解】——OSPF协议(学习笔记)

目录 &#x1f552; 1. 概述&#x1f552; 2. 相关概念&#x1f558; 2.1 基本思想&#x1f558; 2.2 区域及路由&#x1f558; 2.3 链路状态数据库&#x1f564; 2.3.1 点到点网络&#x1f564; 2.3.2 点到多点网络&#x1f564; 2.3.3 广播网络与非广播多址接入网络&#x1f…

反射枚举

1、定义 java的反射机制是在运行状态中&#xff0c;对于任意一个类&#xff0c;都能直到这个类的所有属性和方法&#xff1b;对于任意一个对象&#xff0c;都能够调用他的任意方法和属性&#xff0c;既然能够拿到那么&#xff0c;我们就可以修改部分类型信息&#xff1b;这种动…

软考A计划-电子商务设计师-计算机系统基础知识

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

Delphi11的多线程ⓞ,附送图片处理代码

Delphi11的多线程ⓞ OLD Coder , 习惯使用Pascal 接下来准备启用多线程&#xff0c;毕竟硬件多核&#xff0c;Timer不太爽了&#xff08;曾经的桌面&#xff0c;都是Timer——理解为“片”&#xff09; 突然想写写&#xff0c;不知道还有多少D兄弟们在。 从源码开始 用D11之…

mybatisplus递归传递多个参数 | mybatisplus传递多个参数获取层级数据 | mybatisplus传递多个参数获取树形数据

搜索关键字&#xff1a; mybatisplus关联查询传递参数|"select""树形结构"|"select""树形结构""传参"| "select""many""传参"| "select""column""传参" 1、…

内置工具横向移动

IPCSchtasks IPC: IPC$是共享"命令管道"的资源&#xff0c;它是为了让进程通信而开放的命名管道&#xff0c;连接双方可以建立安全的通道并以此通道进行加密数据交换&#xff0c;从而实现对远程计算机的访问。 利用条件&#xff1a; 1、开放139、445 2、目标开启…

SAP-MM-采购申请审批那些事!

1、ME55不能审批删除行项目的PR 采购申请审批可以设置行项目审批或抬头审批。如果设置为抬头审批时&#xff0c;ME55集中审批时&#xff0c;就会发现有些采购申请时不能审批的&#xff0c; 那么这些采购申请时真的不需要审批么&#xff1f;不是的&#xff0c;经过核对这些采购申…

【每周一书】--(认知觉醒)思考:如何用清爽的情绪面对内卷的当下?

【每周一书】--&#xff08;认知觉醒&#xff09;思考&#xff1a;如何用清爽的情绪面对内卷的当下&#xff1f; 认知觉醒&#xff1a;开启自我改变的原动力焦虑&#xff1a;焦虑的根源完成焦虑定位焦虑选择焦虑环境焦虑难度焦虑 如何拥有清爽的情绪&#xff0c;释放焦虑情绪 认…

STM32F407单片机HAL库CAN2不能接收数据解决方法

最近在使用stm32F407的片子调试can通信&#xff0c;直接在正点原子的代码上修改调试&#xff0c;调试can1的时候&#xff0c;基本没啥问题&#xff0c;收发都正常&#xff0c;使用查询模式和中断模式都可以。但是当修改到can2的时候&#xff0c;可以正常发送数据&#xff0c;但…

WPF 热重载失效了

关于 热重载官方说明&#xff1a; WPF 和 UWP 应用的 XAML 热重载是什么Introducing the .NET Hot Reload experience for editing code at runtime 热重载简单来说&#xff0c;就是点击运行程序后&#xff0c;修改 XAML 代码&#xff0c;应用程序会实时的显示你的修改 为…

Python入门(十三)函数(一)

函数&#xff08;一&#xff09; 1.函数概述2.函数定义2.1向函数传递信息2.2实参和形参 作者&#xff1a;xiou 1.函数概述 函数是带名字的代码块&#xff0c;用于完成具体的工作。要执行函数定义的特定任务&#xff0c;可调用该函数。需要在程序中多次执行同一项任务时&#…

中间件SOME/IP简述

SOME/IP SOME/IP 不是广义上的中间件&#xff0c;严格的来讲它是一种通信协议&#xff0c;但中间件这个概念太模糊了&#xff0c;所以我们也一般称 SOME/IP 为通信中间件。 SOME/IP 全称是 Scalable service-Oriented MiddlewarE over IP。也就是基于 IP 协议的面向服务的可扩…

使用Python绘制M2货币供应率曲线

M2广义货币供应量&#xff1a;流通于银行体系之外的现金加上企业存款、居民储蓄存款以及其他存款&#xff0c;它包括了一切可能成为现实购买力的货币形式&#xff0c;通常反映的是社会总需求变化和未来通胀的压力状态。近年来&#xff0c;很多国家都把M2作为货币供应量的调控目…