React(九)React Hooks

初识Hook

我们到底为什么需要hook那?

函数组件类组件存在问题

函数组件存在的问题:

import React, { PureComponent } from 'react'function HelloWorld2(props) {let message="Hello world"// 函数式组件存在的缺陷:// 1.修改message之后,组件不会重新渲染// 2.就算页面重新渲染:函数会被重新执行,第二次执行时,又会重新给message赋值未Hello world// 3.不能编写类似生命周期的回调:网络请求...return (<div><h1 onClick={e =>message="你好啊"}>内容2:{message}</h1><button>修改文本</button></div>)
}
export class App extends PureComponent {render() {return (<div><h1>App</h1><hr /><HelloWorld2 /></div>)}
}export default App

class组件存在的问题:

1.复杂组件变得难以理解

  • 随着业务增加,class组件会变得越来越复杂
  • 在挂载阶段,可能包含大量的逻辑代码:网络请求、事件监听等;还得在卸载阶段移除掉
  • 逻辑往往混在一起,class难以拆分

2.更加复杂:需要搞清this的指向到底是谁,熟练ES6class

3.组件复用难

  • 状态复用需要通过高阶组件
  • 或者类似Provider、Consumer来共享一些状态,但多次使用Consumer,会导致我们代码存在很多嵌套,难以维护

Hook的出现

hooks的出现就是为了解决上述问题:

  • 它可以在不编写class的情况下使用state以及其它React特性
  • 基本可替代之前所有使用class组件的地方
  • 并不需要直接将所有的代码重构为hooks,因为它向下兼容,可渐进式使用它
  • 只能在函数组件中使用,不能在类组件中使用

Hook实现计数器

 

import React, { memo,useState } from 'react'
// useState()返回的是一个数组
// 元素一:当前状态的值(第一次为初始值),如果不设置则为undefined
// 元素二:更新当前值的函数
const CounterFunction = memo(() => {const [counter,setCounter] = useState(0)return (<div><h2>CounterFunction:{counter}</h2><button onClick={e => setCounter(counter+1)}>+1</button><button onClick={e => setCounter(counter-1)}>-1</button></div>)
})export default CounterFunction

State/Effect

useState

1.useState来自react,需要从react中导入,它是一个hook;

  • 参数:初始化值,如果不设置为undefined;
  • 返回值:数组,包含两个元素;
  • 元素一:当前状态的值(第一调用为初始化值);
  • 元素二:设置状态值的函数;

2.点击button按钮后,会完成两件事情:

  • 调用setCount,设置一个新的值;
  • 组件重新渲染,并且根据新的值返回DOM结构;

3.Hook 就是 JavaScript 函数,这个函数可以帮助你 钩入(hook into) React State以及生命周期等特性;

4.但是使用它们会有两个额外的规则:

  • 只能在函数最外层调用 Hook。不要在循环、条件判断或者子函数中调用
  • 只能在 React 的函数组件中调用 Hook。不要在其他 JavaScript 函数中调用

如果逻辑太复杂,也可以单独封装一个函数修改数据

import React, { memo,useState } from 'react'const CounterFunction = memo(() => {const [message,setMessage] = useState("HelloWorld")function changeMessage(){setMessage("你好呀")}return (<div><h2>CounterFunction:{message}</h2><button onClick={changeMessage}>修改文本</button></div>)
})export default CounterFunction

注意:为什么是useState而不是createState?

解答:因为state只在组件首次渲染时被创建,在下次渲染时,useState返回给我们当前的state。如果每次都创建新的变量,那就不该是状态了。

useEffect

它可以帮在函数组件中完成类似于class生命周期的功能。如网络请求、手动更新DOM、一些事件的监听,都是React更新DOM的一些副作用(Side Effects)。因此对于完成这些功能的Hook就被称为Effect Hook

1.基本使用

我们现在来完成一个需求:使页面的title总是显示count的数字:

 

代码实现:

 

useEffect传入一个回调函数, 这个回调函数在每次页面渲染完成后自动执行。也就是说,每次在函数式组件执行的顺序是:

执行函数组件 => 定义初始状态 => 渲染DOM => 执行useEffect中的回调=> 修改数据 => 重新执行函数组件 => 更新状态 => 渲染最新DOM => 执行useEffect中的回调

不难看出,其实useEffect中的回调相当于完成了componentDidMount和componentDidUpdate做的事情。

2.清除Effect

在类组件编写过程中,某些副作用我们需要在componentWillUnmount中进行清除,如事件总线、Redux中手动调用的subscribe等

useEffect传入的回调函数A本身有一个返回值,返回值里面是回调函数B,可在函数B中进行清除

// 复杂告知react,在执行完当前渲染之后要执行的副作用代码
useEffect(() => {console.log("监听redux中数据变化");// 传入的回调函数,又会返回一个回调函数=> 组件被重新渲染或卸载时执行return () => {console.log("取消监听redux中的数据变化");}
})

3.使用多个Effect

将这些处理逻辑都放在同一个函数里面难维护,要清除也比较混乱,在使用中我们可将逻辑分离到不同的useEffect中:React 将按照 effect 声明的顺序依次调用组件中的每一个 effect;

如下图:

 

但是有一个问题,难道每渲染一次页面,我们的所有effect就要重新调用一次吗?

某些逻辑只需要执行一次即可,怎样才能解决这个问题嘞?

实际上,Effect有两个参数:

  • 参数一:执行的回调函数;
  • 参数二:该useEffect在哪些state发生变化时,才重新执行;(受谁的影响)
import React, { memo, useEffect, useState } from 'react'const App = memo(() => {const [count,setCount] = useState(0)const [message,setMessage] = useState("HelloWorld")useEffect(() => {console.log("修改title");},[count])useEffect(() => {console.log("监听redux中的数据");return () => {}},[])useEffect(() => {console.log("监听eventBus的why事件");return () => {}},[])// 我希望它第一次渲染时执行一次即可useEffect(() => {console.log("发生网络请求");return () => {console.log("会在我们组件被卸载时才会执行");}},[]) return (<div><h2>Count-{count} </h2><button onClick={e => setCount(count+1)}>+1</button><button onClick={e => setMessage("你好啊")}>message({message})</button></div>)
})export default App

打印结果如下图:

 

Context/Reducer

useContext

我们之前在组件中使用类名.contextType = MyContext或MyContext.Consumer来共享数据

但是当多个Context共享时就会存在大量的嵌套:

import React, { Component } from 'react'
import { UserContext,ThemeContext } from './context'export default class App extends Component {// 使用Conetxtrender() {return (<div><UserContext.Consumer>{value => {return (<h2><ThemeContext.Consumer>{value => <span>{value.color}</span>}</ThemeContext.Consumer> </h2>)}}</UserContext.Consumer></div>)}
}

Context Hook允许我们通过Hook来直接获取某个Context的值

import React, { memo ,useContext} from 'react'
import { UserContext,ThemeContext } from './context'const App = memo(() => {// 使用Conetxtconst user = useContext(UserContext)const theme = useContext(ThemeContext)return (<div><div><span>用户信息-{user.name}-{user.age} </span><span>主题色-{theme.color} </span></div></div>)
})export default App

注意:当组件上层最近的 <MyContext.Provider> 更新时,该 Hook 会触发重新渲染,并使用最新传递给 MyContext provider 的context value 值。因此,该数据的更新也是响应式的。

Callback/Memo(性能优化)

useCallback

通常使用useCallback是不希望子组件进行多次渲染,并不是为了进行函数缓存

1.存在问题

 

import React, { memo,useCallback,useState } from 'react'const HYHome = memo(function(props) {const { increment } = propsconsole.log("HYHome被渲染")return (<div><button onClick={increment}>increment+8</button>{/* 100个子组件 */}</div>)
})const App = memo(() => {const [count, setCount] = useState(0)const increment = function() {console.log("increment");setCount(count + 8)}return (<div><h2>App-{count}</h2><button onClick={increment} >+8</button><HYHome increment={increment}/></div>)
})export default App

我希望当子组件没有变化时,不需要重新渲染:

useCallback()返回一个函数的记忆值,在依赖不变的情况下,多次定义返回值是相同的

import React, { memo, useState, useCallback, useRef } from 'react'// useCallback性能优化的点:
// 1.当需要将一个函数传递给子组件时, 最好使用useCallback进行优化, 将优化之后的函数, 传递给子组件——这样的话在某些情况下,子组件就不会重新渲染// props中的属性发生改变时, 组件本身就会被重新渲染
const HYHome = memo(function(props) {const { increment } = propsconsole.log("HYHome被渲染")return (<div><button onClick={increment}>increment+1</button>{/* 100个子组件 */}</div>)
})const App = memo(function() {const [count, setCount] = useState(0)const [message, setMessage] = useState("hello")// 闭包陷阱: useCallback// const increment = useCallback(function foo() {//   console.log("increment")//   setCount(count+1)// }, [count])// 进一步的优化: 当count发生改变时, 也使用同一个函数(了解)// 做法一: 将count依赖移除掉, 缺点: 闭包陷阱// 做法二: useRef, 在组件多次渲染时, 返回的是同一个值const countRef = useRef()countRef.current = countconst increment = useCallback(function foo() {console.log("increment")setCount(countRef.current + 1)}, [])// 普通的函数// const increment = () => {//   setCount(count+1)// }return (<div><h2>计数: {count}</h2><button onClick={increment}>+1</button><HYHome increment={increment}/><h2>message:{message}</h2><button onClick={e => setMessage(Math.random())}>修改message</button></div>)
})export default App

useMemo

1.使用场景:

  • 有大量逻辑计算时,若逻辑输入值无变化,则无需重新计算
  • 对子组件传递相同内容对象时,若无改变则不重新执行

2.函数传入两个参数:

参数一:回调函数

参数二:[逻辑执行依赖的变量]

3.useMemo和useCallback的对比

useMemo拿到的是传入回调函数的返回值,useCallback是回调函数本身

import React, { memo, useCallback } from 'react'
import { useMemo, useState } from 'react'const HelloWorld = memo(function(props) {console.log("HelloWorld被渲染~")return <h2>Hello World</h2>
})// 计算数字
function calcNumTotal(num) {// console.log("calcNumTotal的计算过程被调用~")let total = 0for (let i = 1; i <= num; i++) {total += i}return total
}const App = memo(() => {const [count, setCount] = useState(0)// const result = calcNumTotal(50)// 1.不依赖任何的值, 进行计算const result = useMemo(() => {return calcNumTotal(50)}, [])// 2.依赖count// const result = useMemo(() => {//   return calcNumTotal(count*2)// }, [count])// 3.useMemo和useCallback的对比function fn() {}// const increment = useCallback(fn, [])// const increment2 = useMemo(() => fn, [])// 4.使用useMemo对子组件渲染进行优化// 重新渲染时会定义一个新对象,传入值是没有什么区别的// const info = { name: "why", age: 18 }const info = useMemo(() => ({name: "why", age: 18}), [])return (<div><h2>计算结果: {result}</h2><h2>计数器: {count}</h2><button onClick={e => setCount(count+1)}>+1</button><HelloWorld result={result} info={info} /></div>)
})export default App

Ref/LayoutEffect

useRef

1.获取DOM

import React, { memo, useRef } from 'react'const App = memo(() => {const titleRef = useRef()const inputRef = useRef()function showTitleDom() {console.log(titleRef.current)inputRef.current.focus()}return (<div><h2 ref={titleRef}>Hello World</h2><input type="text" ref={inputRef} /><button onClick={showTitleDom}>查看title的dom</button></div>)
})export default App

2.useRef解决闭包陷阱问题

useRef返回一个ref对象,返回的ref对象再组件的整个生命周期保持不变

import React, { memo, useRef } from 'react'
import { useCallback } from 'react'
import { useState } from 'react'let obj = nullconst App = memo(() => {const [count, setCount] = useState(0)// useRef返回的是一个不变的对象(地址不变)const nameRef = useRef()console.log(obj === nameRef)obj = nameRef// 通过useRef解决闭包陷阱const countRef = useRef()countRef.current = countconst increment = useCallback(() => {setCount(countRef.current + 1)}, [])return (<div><h2>Hello World: {count}</h2><button onClick={e => setCount(count+1)}>+1</button><button onClick={increment}>+1</button></div>)
})export default App

useImperativeHandle/useLayoutEffect(了解)

useImperativeHandle

通过forwardRef可以将子组件的DOM直接暴露给父组件,但是这样也产生了一些问题:

父组件可以拿到子组件的DOM进行任意操作,这样就有点危险了,我们有什么办法解决吗?

  • 可以通过useImperativeHandle的Hook,将传入的ref和useImperativeHandle第二个参数返回的对象绑定到了一起
  • 在父组件中,使用 inputRef.current时,实际上使用的是返回的对象

代码示例:

import React, { memo, useRef, forwardRef, useImperativeHandle } from 'react'const HelloWorld = memo(forwardRef((props, ref) => {const inputRef = useRef()// 如果直接绑定它,权限有点多,对于子组件来说太危险了——我希望只给它保留特定的权限// 子组件对父组件传入的ref进行处理useImperativeHandle(ref, () => {return {focus() {console.log("focus")inputRef.current.focus()},setValue(value) {inputRef.current.value = value}}})return <input type="text" ref={inputRef}/>
}))const App = memo(() => {const titleRef = useRef()const inputRef = useRef()function handleDOM() {// console.log(inputRef.current)inputRef.current.focus()// inputRef.current.value = ""inputRef.current.setValue("哈哈哈")}return (<div><h2 ref={titleRef}>哈哈哈</h2><HelloWorld ref={inputRef}/><button onClick={handleDOM}>DOM操作</button></div>)
})export default App

useLayoutEffect

useLayoutEffect看起来和useEffect非常的相似,事实上他们也只有一点区别而已:

  • useEffect会在渲染的内容更新到DOM上后执行,不会阻塞DOM的更新;
  • useLayoutEffect会在渲染的内容更新到DOM上之前执行,会阻塞DOM的更新;

如果我们希望在某些操作发生之后再更新DOM,那么应该将这个操作放到useLayoutEffect。

import React, { memo, useEffect, useLayoutEffect, useState } from 'react'const App = memo(() => {const [count, setCount] = useState(100)// 点击按钮后,会出现闪烁现象-先变成0,再变成99.xxxx,useEffect(() => {console.log("useEffect")if (count === 0) {setCount(Math.random() + 99)}})// 不会出现闪烁现象,直接变成99.xxxxuseLayoutEffect(() => {console.log("useLayoutEffect")if (count === 0) {setCount(Math.random() + 99)}})console.log("App render")return (<div><h2>count: {count}</h2><button onClick={e => setCount(0)}>设置为0</button></div>)
})export default App

自定义Hook

本质:对函数代码的抽取,实现复用,减少代码逻辑

需求一:所有的组件在创建和销毁时都进行打印

import React, { memo, useEffect, useState } from 'react'// 自定义Hook
function useLogLife(cName) {useEffect(() => {console.log(cName + "组件被创建")return () => {console.log(cName + "组件被销毁")}}, [cName])
}const Home = memo(() => {useLogLife("home")return <h1>Home Page</h1>
})const About = memo(() => {useLogLife("about")return <h1>About Page</h1>
})const App = memo(() => {const [isShow, setIsShow] = useState(true)useLogLife("app")return (<div><h1>App Root Component</h1><button onClick={e => setIsShow(!isShow)}>切换</button>{ isShow && <Home/> }{ isShow && <About/> }</div>)
})export default App

需求二:Context的共享

1.有两个自定义的context

import { createContext } from "react";const UserContext = createContext()
const TokenContext = createContext()export {UserContext,TokenContext
}

2.通过.Provider去包裹根组件

root.render(<userContext.Provider value={{name:'dimple', age: 22}}><tokenContext.Provider value={'dimple555'}><App /></tokenContext.Provider></userContext.Provider>
);

3.封装一个hook方法,只要一调用就能拿到共享的数据

import { useContext } from "react"
import { UserContext, TokenContext } from "../context"function useUserToken() {const user = useContext(UserContext)const token = useContext(TokenContext)return [user, token]
}export default useUserToken

4.在子组件中使用

import React, { memo } from 'react'
import { useUserToken } from "./hooks"// User/Tokenconst Home = memo(() => {const [user, token] = useUserToken()return <h1>Home Page: {user.name}-{token}</h1>
})const About = memo(() => {const [user, token] = useUserToken()return <h1>About Page: {user.name}-{token}</h1>
})const App = memo(() => {return (<div><h1>App Root Component</h1><Home/><About/></div>)
})export default App

需求三:获取鼠标滚动位置

1.定义一个hook

import { useState, useEffect } from "react"function useScrollPosition() {const [ scrollX, setScrollX ] = useState(0)const [ scrollY, setScrollY ] = useState(0)useEffect(() => {function handleScroll() {// console.log(window.scrollX, window.scrollY)setScrollX(window.scrollX)setScrollY(window.scrollY)}window.addEventListener("scroll", handleScroll)//使用完销毁return () => {window.removeEventListener("scroll", handleScroll)}}, [])return [scrollX, scrollY]
}export default useScrollPosition

2.在各个组件中使用

import React, { memo } from 'react'
import useScrollPosition from './hooks/useScrollPosition'
import "./style.css"const Home = memo(() => {const [scrollX, scrollY] = useScrollPosition()return <h1>Home Page: {scrollX}-{scrollY}</h1>
})const About = memo(() => {const [scrollX, scrollY] = useScrollPosition()return <h1>About Page: {scrollX}-{scrollY}</h1>
})const App = memo(() => {return (<div className='app'><h1>App Root Component</h1><Home/><About/></div>)
})export default App

redux hooks

在redux开发中,我们为了让组件和redux结合起来,我们使用了react-redux的connect,这种方式必须使用高阶函数结合返回的高阶组件,且必须编写mapStateToProps和mapDispatchToProps映射的函数,这样其实挺麻烦的

Redux7.1开始,可获取仓库的数据和方法

useSelector:将store映射到组件中

参数一:传入一个回调函数,参数为state,返回需要的数据对象

参数二:通过比较决定组件是否重新渲染

import React, { memo } from 'react'
import { useSelector, useDispatch, shallowEqual } from "react-redux"
import { addNumberAction, changeMessageAction, subNumberAction } from './store/modules/counter'// memo高阶组件包裹起来的组件有对应的特点: 只有props发生改变时, 才会重新渲染
//它默认会比较比较返回的两个对象是否相等,也就是必须返回两个完全相等的对象才可以不引起重新渲染
//那比如message属性值没发生改变就不该渲染该组件的,所以加了shallowEqual
const Home = memo((props) => {const { message } = useSelector((state) => ({message: state.counter.message}), shallowEqual)const dispatch = useDispatch()function changeMessageHandle() {dispatch(changeMessageAction("你好啊, 师姐!"))}console.log("Home render")return (<div><h2>Home: {message}</h2><button onClick={e => changeMessageHandle()}>修改message</button></div>)
})const App = memo((props) => {// 1.使用useSelector将redux中store的数据映射到组件内const { count } = useSelector((state) => ({count: state.counter.count}), shallowEqual)// 2.使用dispatch直接派发actionconst dispatch = useDispatch()function addNumberHandle(num, isAdd = true) {if (isAdd) {dispatch(addNumberAction(num))} else {dispatch(subNumberAction(num))}}console.log("App render")return (<div><h2>当前计数: {count}</h2><button onClick={e => addNumberHandle(1)}>+1</button><button onClick={e => addNumberHandle(6)}>+6</button><button onClick={e => addNumberHandle(6, false)}>-6</button><Home/></div>)
})export default App

 

 

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

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

相关文章

数据清洗的具体内容

&#xff08;一&#xff09;ETL介绍 “ETL&#xff0c;是英文Extract-Transform-Load的缩写&#xff0c;用来描述将数据从来源端经过抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;、加载&#xff08;Load&#xff09;至目的端的过程。ETL一词较…

【动手学深度学习】#7 现代卷积神经网络

主要参考学习资料&#xff1a; 《动手学深度学习》阿斯顿张 等 著 【动手学深度学习 PyTorch版】哔哩哔哩跟李牧学AI 概述 硬件性能和大数据的发展为深度卷积神经网络&#xff08;AlexNet&#xff09;的实现提供了条件。VGG首次将块的思想用于搭建网络。NiN将多层感知机应用在…

Jenkins + CICD流程一键自动部署Vue前端项目(保姆级)

git仓库地址&#xff1a;参考以下代码完成,或者采用自己的代码。 南泽/cicd-test 拉取项目代码到本地 使用云服务器或虚拟机采用docker部署jenkins 安装docker过程省略 采用docker部署jenkins&#xff0c;注意这里的命令&#xff0c;一定要映射docker路径&#xff0c;否则无…

使用 libevent 处理 TCP 粘包问题(基于 Content-Length 或双 \r\n)

在基于 libevent 的 TCP 服务器开发中,处理消息边界是常见需求。以下是两种主流分包方案的完整实现: 一、基于 Content-Length 的分包方案 1.1 数据结构设计 typedef struct {struct bufferevent *bev;int content_length; // 当前消息的预期长度int received_bytes; //…

酶动力学预测工具CataPro安装教程

简介&#xff1a;预测酶动力学参数是酶发现和酶工程中的一项重要任务。在此&#xff0c;研究人员基于蛋白质语言模型、小分子语言模型和分子指纹&#xff0c;提出了一种名为 CataPro 的新酶动力学参数预测算法。该研究从 BRENDA 和 SABIO-RK 数据库中收集了最新的转化率&#x…

项目实战:基于Spring WebFlux与LangChain4j实现大语言模型流式输出

一、背景 在大语言模型&#xff08;LLM&#xff09;应用场景中&#xff0c;GPT-4等模型的响应生成往往需要数秒至数十秒的等待时间。传统同步请求会导致用户面对空白页面等待&#xff0c;体验较差。本文通过Spring WebFlux响应式编程与SSE服务器推送技术&#xff0c;实现类似打…

Go语言入门经典:数组与切片详解

Go语言入门经典&#xff1a;数组与切片详解 数组和切片是Go语言中两种重要的数据结构。数组是一种固定长度的集合&#xff0c;而切片则是一种灵活的动态集合。本章将详细讲解数组和切片的定义、初始化、访问元素、动态操作等内容&#xff0c;帮助读者全面掌握这两种数据结构。…

uniapp中如何用iconfont来管理图标集成到我们开发的项目中

我们在开发不管小程序还是APP的过程中都会用到图标这个东西,那么iconfont提供了对应的功能,怎么才能方便的集成到我们的小程序或者APP项目中,目标是方便调用并且方便管理。 首先注册ICONFONT账号 www.iconfont.cn中去注册即可选择我们需要的图标如下 我们搜索我们需要的图…

从实用的角度聊聊Linux下文本编辑器VIM

本文从实用的角度聊聊Vim的常用命令。何为实用&#xff1f;我举个不实用的例子大家就明白了&#xff0c;用vim写代码。;) “vim是从 vi 发展出来的一个文本编辑器。代码补全、编译及错误跳转等方便编程的功能特别丰富&#xff0c;在程序员中被广泛使用&#xff0c;和Emacs并列成…

优化程序命名:提升专业感与用户体验

在软件开发的广阔天地中&#xff0c;程序命名这一环节常常被开发者们忽视。不少程序沿用着简单直白、缺乏雕琢的名字&#xff0c;如同素面朝天的璞玉&#xff0c;虽不影响其核心功能的发挥&#xff0c;但却在无形之中错失了许多提升用户印象与拓展应用场景的机会。今天&#xf…

LeetCode BFS解决最短路问题

广度优先搜索(BFS, Breadth-First Search)是一种用于图和树结构的遍历算法&#xff0c;特别适合解决无权图的最短路径问题。 算法思想&#xff1a; BFS从起始节点开始&#xff0c;按照"广度优先"的原则&#xff0c;逐层向外扩展搜索&#xff1a; 先访问起始节点的…

[物联网iot]对比WIFI、MQTT、TCP、UDP通信协议

第一步&#xff1a;先理解最基础的关系&#xff08;类比快递&#xff09; 假设你要给朋友寄快递&#xff1a; Wi-Fi&#xff1a;相当于“公路和卡车”&#xff0c;负责把包裹从你家运到快递站。 TCP/UDP&#xff1a;相当于“快递公司的运输规则”。 TCP&#xff1a;顺丰快递&…

基于python的电影数据分析及可视化系统

一、项目背景 随着电影行业的快速发展&#xff0c;电影数据日益丰富&#xff0c;如何有效地分析和可视化这些数据成为行业内的一个重要课题。本系统旨在利用Python编程语言&#xff0c;结合数据分析与可视化技术&#xff0c;为电影行业从业者、研究者及爱好者提供一个便捷的电…

Java8 到 Java21 系列之 Lambda 表达式:函数式编程的开端(Java 8)

Java8 到 Java21 系列之 Lambda 表达式&#xff1a;函数式编程的开端&#xff08;Java 8&#xff09; 系列目录 Java8 到 Java21 系列之 Lambda 表达式&#xff1a;函数式编程的开端&#xff08;Java 8&#xff09;Java 8 到 Java 21 系列之 Stream API&#xff1a;数据处理的…

②EtherCAT/Ethernet/IP/Profinet/ModbusTCP协议互转工业串口网关

型号 协议转换通信网关 EtherCAT 转 Modbus TCP 配置说明 网线连接电脑到模块上的 WEB 网页设置网口&#xff0c;电脑所连网口的网段设置成 192.168.1.X&#xff08;X 是除 8 外的任一数值&#xff09;后&#xff0c;打开浏览器&#xff0c;地址栏输入 192.168.1.8 &#xff…

机器视觉--python基础语法

Python基础语法 1. Python标识符 在 Python 里&#xff0c;标识符由字母、数字、下划线组成。 在 Python 中&#xff0c;所有标识符可以包括英文、数字以及下划线(_)&#xff0c;但不能以数字开头。 Python 中的标识符是区分大小写的。 以下划线开头的标识符是有特殊意义的…

算法日常记录

1. 链表 1.1 删除链表的倒数第 N 个结点 问题描述&#xff1a;给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5] 思路&#xff1a;先让fast跑n步&#xff0c;然后…

14使用按钮实现helloworld(1)

目录 还可以通过按钮的方式来创建 hello world 涉及Qt 中的信号槽机制本质就是给按钮的点击操作,关联上一个处理函数当用户点击的时候 就会执行这个处理函数 connect&#xff08;谁发的信号&#xff0c; 信号类型&#xff0c; 谁来处理这个信息&#xff0c; 怎么处理的&…

【Golang】泛型与类型约束

文章目录 一、环境二、没有泛型的Go三、泛型的优点四、理解泛型&#xff08;一&#xff09;泛型函数&#xff08;Generic function&#xff09;1&#xff09;定义2&#xff09;调用 &#xff08;二&#xff09;类型约束&#xff08;Type constraint&#xff09;1&#xff09;接…

k8s常用总结

1. Kubernetes 架构概览 主节点&#xff08;Master&#xff09;&#xff1a; 负责集群管理&#xff0c;包括 API Server、Controller Manager、Scheduler 和 etcd 存储。 工作节点&#xff08;Node&#xff09;&#xff1a; 运行 Pod 和容器&#xff0c;包含 kubelet、kube-pr…