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

前端学习--React部分

文章目录

  • 前端学习--React部分
    • 前言
    • 1.React简介
      • 1.1React的特点
      • 1.2引入文件
      • 1.3JSX
        • 🍉JSX简介与使用
        • 🍉JSX语法规则
      • 1.4模块与组件
        • 🍉模块
        • 🍉组件
      • 1.5安装开发者工具
    • 2.React面向组件编程
      • 2.1创建组件
        • 🍉函数式组件
        • 🍉类式组件
      • 2.2组件实例的三大属性
        • 🍉state属性
        • 🍉props属性
        • 🍉refs属性
          • 1.字符形式的ref
          • 2.回调函数形式的ref
          • 3.使用createRef(react最推荐的形式)
      • 2.3事件处理
      • 2.4 受控组件和非受控组件
        • 🍉非受控组件
        • 🍉受控组件
      • 2.5高阶函数与函数柯里化
      • 2.6生命周期
        • 🍉引入
        • 🍉react生命周期(旧)
        • 🍉react生命周期(新)
      • 2.7虚拟DOM与DOM Diffing算法
    • 3.react脚手架
      • 3.1创建与启动
      • 3.2react脚手架项目结构
        • 🍉默认文件
        • 🍉编码流程
      • 3.3TodoList案例
        • 🍉todoList案例提要
    • 4.React ajax
      • 4.1简介
      • 4.2实现
      • 4.3配置代理
      • 4.4github搜索案例
        • 🍉axios版本提要
        • 🍉pubsub版本提要
        • 🍉Fetch版本提要(了解)
    • 5.React路由
      • 5.1相关理解
        • 🍉对SPA应用的理解
        • 🍉路由的理解
        • 🍉react-router的理解
      • 5.2路由的基本使用
      • 5.3路由组件与一般组件
      • 5.4NavLink与封装NavLink
      • 5.5Switch的使用
      • 5.6解决样式丢失问题
      • 5.7路由的模糊匹配与严格匹配
      • 5.8Redirect的使用
      • 5.9嵌套路由
      • 5.10向路由组件传递参数
        • 🍉向路由组件传递params参数
        • 🍉向路由组件传递search参数
        • 🍉向路由组件传递state参数
      • 5.11push与repalce
      • 5.12编程式路由导航
      • 5.13withRouter的使用
      • 5.14BrowserRouter与HashRouter
    • 6.React UI组件库
      • 6.1流行的开源React UI组件库
        • 🍉material-ui(国外)
        • 🍉ant-design(国内蚂蚁金服)
    • 7.Redux
      • 7.1Redux简介
      • 7.2Redux的工作流程
        • 🍉redux原理图
        • 🍉redux的三个核心概念
      • 7.3求和案例
        • 🍉纯react版
        • 🍉redux精简版
        • 🍉redux完整版
        • 🍉异步action版
      • 7.4初识react-redux
        • 🍉对react-redux的理解
        • 🍉连接容器组件与UI组件,react-redux基本使用
      • 7.5react-redux的优化
      • 7.6数据共享
      • 7.7纯函数
      • 7.8redux开发者工具
      • 7.9最终版
      • 7.10项目打包

前端学习–React部分

前言

  • 在学习React之前需要掌握的JavaScript基础知识有class(类)、ES6语法规范、npm包管理器、原型、原型链、数组的常用方法、模块化。如果上述知识点你有些淡忘,请前往我的博客主页进行查看。

  • 在讲解过程中,老师会复习旧的知识点,请前往我的gitee链接中进行查看:

    https://gitee.com/marygood/tkreactstudy

  • 下载文件去这里:https://www.bootcdn.cn/(下载的时候看好文件名)

1.React简介

官网给出的定义:用于构建用户界面的JavaScript库(只关注页面)。

通俗定义:将数据渲染为HTML视图的开源JavaScript库。

学习React的原因:

  • 原生JS操作DOM繁琐且效率低,因为用DOM-API操作UI

  • JS直接操作DOM会使浏览器进行大量的重绘重排

  • 原生JS没有组件化编码方案,代码复用率低

1.1React的特点

  • 采用组件化模式,声明式编码,提高开发效率及组件复用率

  • 在React Native中可以使用React语法进行移动端开发

  • 使用虚拟DOM+优秀的Diffing算法,尽量减少与真实DOM的交互

    注:最后一点很重要,它是React高效的原因。

    问:为什么使用虚拟DOM?因为操作页面的代价比操作js大得多。

    实现流程:把数据交给React,它便会拿着这些数据生成虚拟DOM,之后将虚拟DOM转换为真实DOM,最后将这些呈现在页面上。

    补充:数据放在状态(state)中,不是随便放置的。

1.2引入文件

1.react.js (核心库):核心库要在react-dom之前引入

2.react-dom.js :提供操作DOM的react扩展库

3.babel.min.js:解析JSX语法代码转为JS代码的库,即ES6==>ES5;JSX==>JS

需要注意的是引入文件一定要按照这个顺序。

1.3JSX

🍉JSX简介与使用

全称 JavaScript XML ,是react定义的一种类似于XML的JS扩展语法,本质是React.createElement(component, props, ...children)方法的语法糖。JXS最终产生的虚拟DOM就是一个JS对象。

详细代码请前往码云链接。

🍉JSX语法规则

1.定义虚拟DOM时,不要写引号

2.标签中混入js表达式时用{}

3.样式的类名指定不要用class,要用className

4.内联样式,要用style={{key:value}}的形式去写

5.只有一个根标签

6.标签必须闭合

7.标签首字母

​ (1)小写默认为html标签:<good></good> //不是html标签–报错

​ (2)大写默认为组件:<Good></Good> //未定义组件–报错

1.4模块与组件

🍉模块
  • 向外界提供特定功能的js程序。随着业务逻辑增加,代码越来越多且复杂,此时js一般会拆成多个js文件来编写,一般一个js文件就是一个模块
  • 作用:复用js,简化js的编写,提高js的运行效率
  • 模块化:当应用的js都以模块来编写的, 这个应用就是一个模块化的应用
🍉组件
  • 用来实现局部功能效果的代码和资源的集合(html/css/js/image等等)。比如一个功能齐全的Header栏就是一个组件。
  • 复用编码, 简化项目编码, 提高运行效率
  • 组件化:当应用是以多组件的方式实现, 这个应用就是一个组件化的应用

1.5安装开发者工具

我自己直接在谷歌应用商店下载的,现在的发布者已经变为Meta。

打开扩展程序,找到安装好的React Developer Tool,点击详情,并勾选上以下内容。

请添加图片描述

2.React面向组件编程

2.1创建组件

🍉函数式组件

简单组件,没有state,本身没有三大属性,不过通过hooks也有了三大属性。

🍉类式组件

复杂组件,有state,有三大属性。

2.2组件实例的三大属性

🍉state属性
  • state是组件对象最重要的属性, 值是对象(可以包含多个key-value的组合)
  • 组件被称为"状态机", 通过更新组件的state来更新对应的页面显示(重新渲染组件)

代码实例:切换天气状态(简写版)

<script type="text/babel">// 实际开发中一定是写精简版本的// 1.创建组件class Weather extends React.Component{// 初始化状态state={isHot:false,wind:"微风"}render() {// 读取状态(解构赋值)const {isHot,wind} =this.state// 注意此处React事件绑定的写法return <h1 onClick={this.changeWeather}>今天天气{isHot ? '热':'凉'}{wind}</h1>}// 和完整写法比这里用了箭头函数,就不再使用构造器changeWeather=() => {// 获取原来的isHot值const isHot=this.state.isHot// 注意:状态(不可以直接更改)必须通过setState进行更新,且更新是一种合并,不是替换。// this.state.isHot=!isHot //错误写法this.setState({isHot:!isHot})}}// 2.渲染组件到页面ReactDOM.render(<Weather/>,document.getElementById('test'))</script>

这里需要注意的是在render函数中创建虚拟DOM时,直接在标签中绑定事件,且事件写法不同于原生JS,如原生JS中的onclick事件,在react中要写成onClick,其他同理。其次,需要注意的是状态数据不能直接修改或更新,要使用setState。

🍉props属性
  • 通过标签属性(创建虚拟DOM时直接添加的数据)从组件外向组件内传递变化的数据

  • 传递props,即传递标签属性 – props批量传递标签属性

  • 组件标签的所有属性都保存在props中

  • props是只读的,不要在组件内部修改props

  • 如果想对标签属性进行类型、必要性限制,需要引入prop-types库(不是必须的,看情况)

代码实例: 自定义用来显示人员信息

标准形式 – 写在外部

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>hello_react</title>
</head>
<body><!-- 准备好一个容器 --><div id="test"></div><div id="test1"></div><div id="test2"></div><!-- 引入依赖 ,引入的时候,必须就按照这个步骤--><!-- 引入react核心库 --><script src="../js/react.development.js" type="text/javascript"></script><!-- 引入react-dom,用于支持react操作DOM --><script src="../js/react-dom.development.js" type="text/javascript"></script><!-- 引入babel,用于将jsx转为js --><script src="../js/babel.min.js" type="text/javascript"></script><!--引入对于组件标签的限制--><script src="../js/prop-types.js"></script><!-- 此处一定要写babel,不写会默认为js,将报错 --><script type="text/babel">// 1.创建组件class Person extends React.Component{render() {console.log(this)const {name,age,sex} = this.propsreturn(<ul><li>姓名:{name}</li><li>性别:{sex}</li><li>年龄:{age+1}</li></ul>)}}// 对标签属性进行类型、必要性限制Person.propTypes={name:PropTypes.string.isRequired, //限制name必传,且为字符串sex:PropTypes.string,//限制sex为字符串age:PropTypes.number,//限制age为数值speak:PropTypes.func,//现在speak为函数}// 指定默认标签属性值Person.defaultProps={sex:'男',age:18}// 2.渲染组件到页面ReactDOM.render(<Person name="Bob" age={19} speak={speak}/>,document.getElementById("test"))ReactDOM.render(<Person name="Tom" sex="男"/>,document.getElementById("test1"))// 另一种 写法const p={name:"Lily",age:30,sex:"女"}ReactDOM.render(<Person {...p}/>,document.getElementById('test2'))function speak() {console.log('我说话了')}</script>
</body>
</html>

简写形式 – 写在内部

  <!-- 此处一定要写babel,不写会默认为js,将报错 --><script type="text/babel">// 1.创建组件class Person extends React.Component{// 对标签属性进行类型、必要性限制static propTypes={name:PropTypes.string.isRequired, //限制name必传,且为字符串sex:PropTypes.string,//限制sex为字符串age:PropTypes.number,//限制age为数值}// 指定默认标签属性值static defaultProps={sex:'男',age:18}render() {console.log(this)const {name,age,sex} = this.propsreturn(<ul><li>姓名:{name}</li><li>性别:{sex}</li><li>年龄:{age+1}</li></ul>)}}// 2.渲染组件到页面ReactDOM.render(<Person name="Bob"/>,document.getElementById("test"))</script>

注意:

  • 首字母小写的propTypes是类里的属性规则
  • 首字母大写的PropTypes是prop-types库里的内置对象

函数组件使用props

  <!-- 此处一定要写babel,不写会默认为js,将报错 --><script type="text/babel">// 注意:到目前学习阶段,函数组件只能使用三大属性中propsfunction Person(props){const {name,age,sex} = propsreturn(<ul><li>姓名:{name}</li><li>性别:{sex}</li><li>年龄:{age}</li></ul>)}// 渲染组件到页面ReactDOM.render(<Person name='Bob' sex='male' age='12'/>,document.getElementById('test'))</script>
🍉refs属性

组件内的标签可以定义ref属性来标识自己。this.refs可以拿到真实DOM。

1.字符形式的ref
  <!-- 此处一定要写babel,不写会默认为js,将报错 --><script type="text/babel">class Demo extends React.Component{// 展示左侧输入框数据showData = () =>{const {input1}=this.refsalert(input1.value)// console.log(this)}// 展示右侧输入框的数据showDataRight=()=>{const {input2}=this.refsalert(input2.value)}render(){return (<div><input ref="input1" type="text" placeholder="点击弹出提示数据" />&nbsp;<button  onClick = {this.showData}>点击</button>&nbsp;<input ref="input2" onBlur={this.showDataRight} type="text" placeholder="失去焦点弹出提示数据" /></div>)}}// 渲染组件到页面ReactDOM.render(<Demo/>,document.getElementById('test'))/* ref与refs介绍:1.只要有ref标识就会有refs属性(有ref就不用id了,功能类似)2.这节使用的字符串形式的ref比较老旧,不推荐使用,因为效率低*/</script>
2.回调函数形式的ref

回调函数:一种特殊的函数。它会作为参数传递给另一个函数,并在该函数被调用执行完毕后执行。

<script type="text/babel">class Demo extends React.Component{// 展示左侧输入框数据showData = () =>{const {input1}=thisalert(input1.value)}// 展示右侧输入框的数据showDataRight=()=>{const {input2}=thisalert(input2.value)} // currentNode当前节点,两种写法,一种是完整版,一种是精简版render(){return (<div><input ref={(currentNode)=>{this.input1=currentNode}} type="text" placeholder="点击弹出提示数据" />&nbsp;<button  onClick = {this.showData}>点击</button>&nbsp;<input ref={ c => this.input2=c } onBlur={this.showDataRight} type="text" placeholder="失去焦点弹出提示数据" /></div>)}}// 渲染组件到页面ReactDOM.render(<Demo/>,document.getElementById('test'))</script>
3.使用createRef(react最推荐的形式)
  <!-- 此处一定要写babel,不写会默认为js,将报错 --><script type="text/babel">class Demo extends React.Component{// React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点,该容器的使用是需要一一对应的myRef=React.createRef()// myRefRight=React.createRef()// 展示左侧输入框数据showData = () =>{alert(this.myRef.current.value)}// 展示右侧输入框的数据showDataRight=()=>{alert(this.myRefRight.current.value)} // currentNode当前节点,两种写法,一种是完整版,一种是精简版render(){return (<div><input ref={this.myRef} type="text" placeholder="点击弹出提示数据" />&nbsp;<button onClick = {this.showData}>点击</button>&nbsp;<input ref={this.myRefRight=React.createRef()} onBlur={this.showDataRight} type="text" placeholder="失去焦点弹出提示数据" /></div>)}}// 渲染组件到页面ReactDOM.render(<Demo/>,document.getElementById('test'))/* createRef(API)这种方式,是目前react最推荐的。 */

2.3事件处理

<!-- 此处一定要写babel,不写会默认为js,将报错 --><script type="text/babel">class Demo extends React.Component{/* 1.通过onXxx属性指定事件处理函数(注意大小写)a.React使用的是自定义(合成)事件,而不是使用原生DOM事件 -- 为更好的兼容性b.React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)-- 为高效2.通过event.target得到发生事件的DOM元素对象 -- 不要过度使用ref(有事件就不用ref)*/// 创建ref容器myRef=React.createRef()// 展示左侧输入框数据showData = () =>{alert(this.myRef.current.value)}// 展示右侧输入框的数据showDataRight=(event)=>{alert(event.target.value)} // currentNode当前节点,两种写法,一种是完整版,一种是精简版render(){return (<div><input ref={this.myRef} type="text" placeholder="点击弹出提示数据" />&nbsp;<button onClick = {this.showData}>点击</button>&nbsp;<input onBlur={this.showDataRight} type="text" placeholder="失去焦点弹出提示数据" /></div>)}}// 渲染组件到页面ReactDOM.render(<Demo/>,document.getElementById('test'))</script>

2.4 受控组件和非受控组件

🍉非受控组件
<!-- 此处一定要写babel,不写会默认为js,将报错 --><script type="text/babel">class Demo extends React.Component{login = (event) =>{event.preventDefault() //阻止表单提交const {saveName,savePwd}=thisalert(`姓名:${saveName.current.value},密码:${savePwd.current.value}`)}render(){return (<form action="http://www.baidu.com" onSubmit={this.login}>用户名:<input ref={this.saveName=React.createRef()} type = "text" name ="username"/>密码<input ref={this.savePwd=React.createRef()} type = "password" name ="password"/><button>登录</button></form>)}}// 渲染组件到页面ReactDOM.render(<Demo/>,document.getElementById('test'))/* 现用现取,就属于非受控组件 */</script>
🍉受控组件
<!-- 此处一定要写babel,不写会默认为js,将报错 --><script type="text/babel">class Demo extends React.Component{saveName = (event) =>{this.setState({username:event.target.value})}  savePwd=(event)=>{this.setState({password:event.target.value})}login = (event) =>{event.preventDefault() //阻止表单提交const {username,password} = this.state //注意:username和password是值alert(`姓名:${username},密码:${password}`)}render(){return (<form action="http://www.baidu.com" onSubmit={this.login}>用户名:<input onChange={this.saveName} type = "text" name ="username"/>密码<input onChange={this.savePwd} type = "password" name ="password"/><button>登录</button></form>)}}// 渲染组件到页面ReactDOM.render(<Demo/>,document.getElementById('test'))/* 随着输入维护状态,就属于受控组件。(类似vue中的双向数据绑定)通俗理解:通过ref就是非受控,通过change就是受控。建议写受控组件*/</script>

2.5高阶函数与函数柯里化

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>hello_react</title>
</head>
<body><!-- 准备好一个容器 --><div id="test"></div><!-- 引入依赖 ,引入的时候,必须就按照这个步骤--><!-- 引入react核心库 --><script src="../js/react.development.js" type="text/javascript"></script><!-- 引入react-dom,用于支持react操作DOM --><script src="../js/react-dom.development.js" type="text/javascript"></script><!-- 引入babel,用于将jsx转为js --><script src="../js/babel.min.js" type="text/javascript"></script><!--引入对于组件标签的限制--><script src="../js/prop-types.js"></script><!-- 此处一定要写babel,不写会默认为js,将报错 --><script type="text/babel">class Demo extends React.Component{// saveFormData就是高阶函数saveFormData = (dataType) =>{return(event)=>{// 调用变量形式的对象属性名// 可以理解为加上中括号的dataType就成为了一个属性this.setState({[dataType]:event.target.value})}}  login = (event) =>{event.preventDefault() //阻止表单提交const {username,password} = this.state //注意:username和password是值alert(`姓名:${username},密码:${password}`)}// 能保证onChange等于的是一个函数即可,无需过度在意加不加括号render(){return (<form action="http://www.baidu.com" onSubmit={this.login}>用户名:<input onChange={this.saveFormData('username')} type = "text" name ="username"/>密码<input onChange={this.saveFormData('password')} type = "password" name ="password"/><button>登录</button></form>)}}// 渲染组件到页面ReactDOM.render(<Demo/>,document.getElementById('test'))/* 高阶函数:如果一个函数符合下面2个规范中的任何一个,那么该函数就是高阶函数。1.若A函数,接收的参数是一个函数,那么A就可以称之为高阶函数2.若A函数,调用的返回值依然是一个函数,那么A就可以称之为高阶函数常见的高阶函数有:Promise、setTimeout、arr.map()等等函数的柯里化:通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式。*/</script>
</body>
</html>

不过也不是一定要用函数的柯里化实现,下面介绍不用函数柯里化实现的方法:

<!-- 此处一定要写babel,不写会默认为js,将报错 --><script type="text/babel">class Demo extends React.Component{// saveFormData就是高阶函数saveFormData = (dataType,event) =>{this.setState({[dataType]:event.target.value})}  login = (event) =>{event.preventDefault() //阻止表单提交const {username,password} = this.state //注意:username和password是值alert(`姓名:${username},密码:${password}`)}// 能保证onChange等于的是一个函数即可,无需过度在意加不加括号render(){return (<form action="http://www.baidu.com" onSubmit={this.login}>用户名:<input onChange={event => this.saveFormData('username',event)} type = "text" name ="username"/>密码<input onChange={event => this.saveFormData('password',event)} type = "password" name ="password"/><button>登录</button></form>)}}// 渲染组件到页面ReactDOM.render(<Demo/>,document.getElementById('test'))</script>

2.6生命周期

🍉引入
  1. React组件中包含一系列生命周期回调函数。我们在定义组件时,会在特定的生命周期回调函数中做特定的工作。
  2. 生命周期回调函数也可以称为:生命周期钩子函数 == 生命周期函数 ==生命周期钩子。

补充react写法

  1. 行内样式写法:style={{opacity:opacity}}
  2. 对象中属性名和属性值相同时触发简写:{opacity:opacity}简写为{opacity}
🍉react生命周期(旧)

请添加图片描述

1.初始化阶段: 由ReactDOM.render()触发—初次渲染1)constructor()2)componentWillMount()3)render(): 常用,初始化或者更新渲染4)componentDidMount(): 常用,一般在这个钩子中做一些初始化的事,如开启定时器、发送网络请求、订阅消息
2.更新阶段: 由组件内部this.setSate()或父组件重新render触发1)shouldComponentUpdate() -- 闸门,返回值是布尔值,为true时执行后续代码2)componentWillUpdate()3)render()4)componentDidUpdate()
3.卸载组件: 由ReactDOM.unmountComponentAtNode()触发1)componentWillUnmount() :常用,一般在这个钩子中做一些收尾的事,如关闭定时器、取消订阅消息
🍉react生命周期(新)

请添加图片描述

1.初始化阶段: 由ReactDOM.render()触发—初次渲染1)constructor()2)getDerivedStateFromProps3)render(): 常用,初始化或者更新渲染4)componentDidMount(): 常用,一般在这个钩子中做一些初始化的事,如开启定时器、发送网络请求、订阅消息
2.更新阶段: 由组件内部this.setSate()或父组件重新render触发1)getDerivedStateFromProps2)shouldComponentUpdate()3)render()4)getSnapshotBeforeUpdate --5)componentDidUpdate()
3.卸载组件: 由ReactDOM.unmountComponentAtNode()触发1)componentWillUnmount() :常用,一般在这个钩子中做一些收尾的事,如关闭定时器、取消订阅消息
注:新出的也不常用    	

2.7虚拟DOM与DOM Diffing算法

经典面试题:
1)react/vue中的key有什么作用?(key的内部原理是什么?)
2)为什么遍历列表时,key最好不要用index?1.虚拟DOM中key的作用:1)简单的说:key是虚拟DOM对象的标识,在更新显示时key起着极其重要的作用。2)详细的说:当状态中的数据发生变化时,react会根据【新数据】生成【新的虚拟DOM】,随后react进行【新虚拟DOM】与【旧虚拟DOM】的diff比较,比较规则如下:a.旧虚拟DOM中找到了与新虚拟DOM相同的key:(1) 若虚拟DOM中内容没变, 直接使用之前的真实DOM(2) 若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOMb.旧虚拟DOM中未找到与新虚拟DOM相同的key:根据数据创建新的真实DOM,随后渲染到到页面
2.用index作为key可能会引发的问题:1)若对数据进行:逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。2)如果结构中还包含输入类的DOM(如input,虚拟DOM中标签属性少,input没有value属性):会产生错误DOM更新 ==> 界面有问题。3)注意! 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。
3.开发中如何选择key?1)最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。2)如果确定只是简单的展示数据,用index也是可以的。

3.react脚手架

3.1创建与启动

  1. 全局安装:npm i -g create-react-app
  2. 切换到想要创建项目的目录,使用命令:create-react-app hello-react。(hello-react是文件名)
  3. 用VSCode打开文件,并在终端(软件内)启动项目:npm start

3.2react脚手架项目结构

🍉默认文件
public -- 静态资源文件夹
favicon.icon -- 网站页签图标
index.html -- 主页面
logo192.png -- logo图
logo512.png -- logo图
manifest.json -- 应用加壳的配置文件
robots.txt -- 爬虫协议文件
src -- 源码文件夹
App.css -- App组件的样式,App.js里引用
App.js -- App组件,子组件可以都写在components文件夹里,子组件文件夹首字母大写。路由组件写在pages文件夹
App.test.js -- 用于给App做测试
index.css -- 样式,通用样式,入口文件里引用
index.js -- 入口文件 
logo.svg -- logo图 
reportWebVitals.js -- 页面性能分析文件(需要web-vitals库的支持)
setupTests.js -- 组件单元测试的文件(需要jest-dom库的支持)
🍉编码流程
拆分组件: 拆分界面,抽取组件
实现静态组件: 使用组件实现静态页面效果
实现动态组件:3.1 动态显示初始化数据3.1.1 数据类型3.1.2 数据名称3.1.3 保存在哪个组件?3.2 交互(从绑定事件监听开始)

3.3TodoList案例

详细代码见前言中的gitee链接。

🍉todoList案例提要
  1. 写法的注意:class -- classNamestyle="" -- style={{}}
  2. 动态初始化列表,如何确定将数据放在哪个组件的state中?
    1)某个组件使用:放在其自身的state
    2)某些组件使用:放在他们共同的父组件state中(官方称此操作为:状态提升)
  3. 关于父子之间通信:
    1)【父组件】给【子组件】传递数据:通过props传递
    2)【子组件】给【父组件】传递数据:通过props传递,要求父提前给子传递一个函数
  4. 注意defaultCheckedchecked的区别,类似的还有:defaultValuevalue
  5. 状态在哪里,操作状态的方法就在哪里

4.React ajax

4.1简介

  1. React本身只关注于界面, 并不包含发送ajax请求的代码
  2. 前端应用需要通过ajax请求与后台进行交互(json数据)
  3. react应用中需要集成第三方ajax库(或自己封装,但是基本不会自己封装)

4.2实现

  1. jQuery: 要操作DOM,并且比较重, 如果需要另外引入不建议使用
  2. axios: 轻量级, 建议使用
    1)封装XmlHttpRequest对象的ajax
    2)promise风格
    3)可以用在浏览器端和node服务器端

4.3配置代理

方法一

在package.json中追加配置:"proxy":"http://localhost:5000"

  • 优点:配置简单,前端请求资源时可以不加任何前缀。
  • 缺点:不能配置多个代理。
  • 工作方式:上述方式配置代理,当请求了3000不存在的资源时,那么该请求会转发给5000 (优先匹配前端资源)

方法二

  1. 创建代理配置文件:在src文件夹下创建setupProxy.js文件。

  2. 编写setupProxy.js配置具体代理规则:

    //这个文件名是固定的,不可改
    const proxy = require('http-proxy-middleware')module.exports = function(app) {app.use(proxy('/api1', {  //api1是需要转发的请求(所有带有/api1前缀的请求都会转发给5000)target: 'http://localhost:5000', //配置转发目标地址(能返回数据的服务器地址)changeOrigin: true, //控制服务器接收到的请求头中host字段的值(可以欺骗一下浏览器)/*changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:3000changeOrigin默认值为false,但我们一般将changeOrigin值设为true*/pathRewrite: {'^/api1': ''} //去除请求前缀/api1,保证交给后台服务器的是正常请求地址(必须配置)}),proxy('/api2', { target: 'http://localhost:5001',changeOrigin: true,pathRewrite: {'^/api2': ''}}))
    }
    
  3. 说明:

    • 优点:可以配置多个代理,可以灵活的控制请求是否走代理。

    • 缺点:配置繁琐,前端请求资源时必须加前缀。

  4. react 18版本写法:在后续的github案例中我自己用的这个。

    //react 18版本写法
    const {createProxyMiddleware} = require('http-proxy-middleware')module.exports = function (app) {app.use(createProxyMiddleware('/api1', {target: 'http://localhost:5000',changeOrigin: true,pathRewrite: {'^/api1': ''}}))
    }
    

4.4github搜索案例

详细代码在前言的gitee链接中。

🍉axios版本提要
  • 连续解构赋值+重命名:

    const {keyWordElement:{value:keyWord}} = this
    
  • 三元表达式:

    isFirst ? <h2>欢迎使用,输入关键字,随后点击搜索</h2> :
    isLoading ? <h2>Loading......</h2> :
    err ? <h2 style={{color:'red'}}>{err}</h2> 
    
  • 如果你说什么都展现不出效果:

    //App.jsx文件
    export default class App extends Component{...updateAppState = (stateObj) =>{this.setState({...stateObj})}...
    }
    
🍉pubsub版本提要
工具库: PubSubJS
下载: npm install pubsub-js --save
使用:
1) import PubSub from ‘pubsub-js’ //引入
2) PubSub.subscribe(‘delete’, function(data){ }); //订阅
3) PubSub.publish(‘delete’, data) //发布
4) 要在组件的componentWilUnmount中取消订阅
注:谁用谁订阅,谁有订阅者所需的数据谁就发布。
🍉Fetch版本提要(了解)
发送ajax请求的方法:原生AJAX:xhrjQuery:对xhr的封装axios:对xhr的封装fetch:不是库,是windows内置,且是Promise风格。
注:有些文章拉踩,不过还是要以主流为主。
fetch的特点:关注分离,兼容性不高,老版本浏览器不支持。

5.React路由

5.1相关理解

🍉对SPA应用的理解
  1. 单页Web应用(single page web application,SPA)。
  2. 整个应用只有一个完整的页面。
  3. 点击页面中的链接不会刷新页面,只会做页面的局部更新。
  4. 数据都需要通过ajax请求获取, 并在前端异步展现。
🍉路由的理解
  • 什么是路由?

    1. 一个路由就是一个映射关系(key:value)
    2. key为路径, value可能是function或component
  • 路由的分类

    1.后端路由:

    • 理解:value是function, 用来处理客户端提交的请求。
    • 注册路由: router.get(path, function(req, res))
    • 工作过程:当node接受到一个请求时,根据请求路径找到匹配的路由,调用路由中的函数来处理请求,返回响应数据。

    2.前端路由:

    • 浏览器端路由,value是component,用于展示页面内容。
    • 注册路由: <Route path="/test" component={Test}>
    • 工作过程:当浏览器的path变为/test时, 当前路由组件就会变为Test组件。
🍉react-router的理解
  1. react的一个插件库。

    • 安装:npm i react-router-dom@5。(注意是5版本)
  2. 专门用来实现一个SPA应用。

  3. 基于react的项目基本都会用到此库。

5.2路由的基本使用

  1. 明确好界面中的导航区、展示区
  2. 导航区的a标签改为Link标签 <Link to="/xxxxx" >Demo</Link>
  3. 展示区写Route标签进行路径的匹配<Route path='/xxxx 'component={Demo}/>
  4. <App>的最外侧包裹了一个<BrowserRouter><HashRouter>
  5. 注意:详细代码见gitee。

5.3路由组件与一般组件

  1. 写法不同

    • 一般组件:<Demo/ >
    • 路由组件: <Route path="/demo" component={Demo}/>
  2. 存放文件位置不同:

    • 一般组件:在components文件中
    • 路由组件:在pages文件中
  3. 接收到的props不同:

    • 一般组件:写组件标签时传递了什么,就能收到什么

    • 路由组件:接收到三个固定的属性

      1. history:

        go: f go(n)
        goBack: f goBack()
        goForward: f goForward()
        push: f push(path,state)
        replace: f replace(path, state)
        
      2. location:

        pathname: "/about"
        search: ""
        state: undefined
        
      3. match:

        params: {}
        path: "/about"
        url: "/about"
        

5.4NavLink与封装NavLink

  1. NavLink可以实现路由链接的高亮,通过activeClassName指定样式名
  2. 标签体内容是一个特殊的标签属性
  3. 通过this.props.children可以获取标签体内容
  4. 注意:详细代码见gitee。

5.5Switch的使用

  1. 通常情况下,path和component是一一对应的关系。
  2. Switch可以提高路由匹配效率(单一匹配)。
  3. 详细代码见gitee。

5.6解决样式丢失问题

  1. public/index.html 中引入样式时不写./写/(常用)

    <link rel="stylesheet" href="css/bootstrap.css">
    
  2. public/index.html 中引入样式时不写﹒/写%PUBLIC_URL%(常用)

    <link rel="stylesheet" href="%PUBLIC_URL%/css/bootstrap.css">
    
  3. 使用HashRouter (不常用)

    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import App from './App';
    import {BrowserRouter, HashRouter} from "react-router-dom";const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(<HashRouter><App/></HashRouter>
    );
    

5.7路由的模糊匹配与严格匹配

  1. 默认使用的是模糊匹配(简单记:【输入的路径】必须包含要【匹配的路径】,且顺序要一致)
  2. 开启严格匹配:<Route exact={true} path="/about" component={About}/>
  3. 严格匹配不要随便开启,需要再开,有些时候开启会导致无法继续匹配二级路由

5.8Redirect的使用

  1. 一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由。

  2. 具体编码:

    <Switch><Route path="/about" component={About}/><Route path="/home" component={Home}/><Redirect to="/about"/>
    </Switch>
    

5.9嵌套路由

  1. 注册子路由时要写上父路由的path值
  2. 路由的匹配是按照注册路由的顺序进行的
  3. 注意:详细代码见gitee

5.10向路由组件传递参数

🍉向路由组件传递params参数
  • 路由链接(携带参数):<Link to='/demo/test/tom/18'}>详情</Link>

  • 注册路由(声明接收):<Route path="/demo/test/:name/:age" component={Test}/>

  • 接收参数:const {id,title} = this.props.match.params

🍉向路由组件传递search参数
  • 路由链接(携带参数):<Link to=' /demo/test?name=tom&age=18'}>详情</Link>

  • 注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>

  • 接收参数:const isearch} = this.props.location

  • 备注:获取到的search是urlencoded编码字符串,需要借助querystring解析

🍉向路由组件传递state参数
  • 路由链接(携带参数):

    <Link to={{path:' /demo/test',state:{name : ' tom' ,age:18]}}>详情</Link>注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
    
  • 接收参数:this.props.location.state

  • 备注:刷新也可以保留住参数

5.11push与repalce

  • push:留下记录
  • repalce:不留记录
  • 注意:详细代码见gitee

5.12编程式路由导航

  • 借助this.prosp.history对象上的API对操作路由跳转、前进、后退

    this.prosp.history.push()
    this.prosp.history.replace()
    this.prosp.history.goBack()
    this.prosp.history.goForward()
    this.prosp.history.go()
    
  • 注意:详细代码见gitee

5.13withRouter的使用

  1. withRouter可以加工一般组件,让一般组件具备路由组件所特有的API
  2. withRouter的返回值是一个新组件
import React, {Component} from 'react';
import {withRouter} from "react-router-dom";class Header extends Component {back = () => {this.props.history.goBack()}forward = () => {this.props.history.goForward()}go = () => {this.props.history.go(2)}render() {// console.log('Header组件收到的props是', this.props)return (<div><div className="page-header"><h2>React Router Demo</h2><button onClick={this.back}>回退</button><button onClick={this.forward}>前进</button><button onClick={this.go}>go</button></div></div>);}
}export default withRouter(Header);

5.14BrowserRouter与HashRouter

  1. 底层原理不一样:
    (1) BrowserRouter使用的是H5的history API,不兼容IE9及以下版本。
    (2) HashRouter使用的是URL的哈希值
  2. path表现形式不一样
    (1) BrowserRouter的路径中没有#,例如:localhost:3000/demo/test
    (2) HashRouter的路径包含#,例如: localhost:3000/#/demo/test
  3. 刷新后对路由state参数的影响
    (1) BrowserRouter没有任何影响,因为state保存在history对象中。
    (2) HashRouter刷新后会导致路由state参数的丢失。
  4. 备注: HashRouter可以用于解决一些路径错误相关的问题。
  5. 总的来讲BrowserRouter常用。

6.React UI组件库

6.1流行的开源React UI组件库

🍉material-ui(国外)
  1. 官网: http://www.material-ui.com/#/

  2. Github:https://github.com/callemall/material-ui

🍉ant-design(国内蚂蚁金服)
  1. 官网: https://ant.design/index-cn

  2. Github: https://github.com/ant-design/ant-design/

7.Redux

7.1Redux简介

  • 什么是Redux?
  1. redux是一个专门用于做状态管理的JS库(不是react插件库)。
  2. 它可以用在react, angular, vue等项目中, 但基本与react配合使用。
  3. 作用: 集中式管理react应用中多个组件共享的状态。
  • 什么情况下需要使用redux?
  1. 某个组件的状态,需要让其他组件可以随时拿到(共享)。
  2. 一个组件需要改变另一个组件的状态(通信)。
  3. 总体原则:能不用就不用, 如果不用比较吃力才考虑使用。

7.2Redux的工作流程

🍉redux原理图

在这里插入图片描述

🍉redux的三个核心概念
  • action
  1. 动作的对象
  2. 包含2个属性
    1. type:标识属性, 值为字符串, 唯一, 必要属性
    2. data:数据属性, 值类型任意, 可选属性
  3. 例子:{ type: 'ADD_STUDENT',data:{name: 'tom',age:18} }
  • reducer
  1. 用于初始化状态、加工状态。
  2. 加工时,根据旧的state和action, 产生新的state的纯函数。
  • store
  1. 将state、action、reducer联系在一起的对象
  2. 如何得到此对象?
    1. import {createStore} from ‘redux’
    2. import reducer from ‘./reducers’
    3. const store = createStore(reducer)
  3. 此对象的功能?
    1. getState(): 得到state
    2. dispatch(action): 分发action, 触发reducer调用, 产生新的state
    3. subscribe(listener): 注册监听, 当产生了新的state时, 自动调用

7.3求和案例

🍉纯react版

详细代码见gitee。

🍉redux精简版
  • store.js:
    • 引入redux中的createStore函数,创建一个store
    • createstore调用时要传入一个为其服务的reducer
    • 记得暴露store对象
  • count_reducer.js:
    • reducer的本质是一个函数,接收: preState,action,返回加工后的状态
    • reducer有两个作用:初始化状态,加工状态
    • reducer被第一次调用时,是store自动触发的,传递的preState是undefined
  • 在index.js中检测store中状态的改变,一旦发生改变重新渲染<App/>
  • 备注: redux只负责管理状态,至于状态的改变驱动着页面的展示,要靠我们自己写。
  • 注意:详细代码见gitee
🍉redux完整版
  • 新增文件:
  1. count_action.js 专门用于创建action对象
  2. constant.js放置容易写错的type值
  • 注意:详细代码见gitee
🍉异步action版
  • 明确:延迟的动作不想交给组件自身,想交给action

  • 何时需要异步action:想要对状态进行操作,但是具体的数据靠异步任务返回。

  • 具体编码:

    • yarn add redux-thunk,并配置在store中
    • 创建action的函数不再返回一般对象,而是一个函数,该函数中写异步任务。
    • 异步任务有结果后,分发一个同步的action去真正操作数据。
  • 备注:异步action不是必须要写的,完全可以自己等待异步任务的结果了再去分发同步action

  • 注意:详细代码见gitee

7.4初识react-redux

🍉对react-redux的理解

在这里插入图片描述

🍉连接容器组件与UI组件,react-redux基本使用
  • 明确两个概念:

    • UI组件:不能使用任何redux的api,只负责页面的呈现、交互等。
    • 容器组件:负责和redux通信,将结果交给UT组件。
  • 如何创建一个容器组件-----靠react-redux 的connect函数

    • connect(mapStateToProps,mapDispatchToProps)(UI组件)
    • mapstateToProps:映射状态,返回值是一个对象
    • mapDispatchToProps:映射操作状态的方法,返回值是一个对象
  • 备注1:容器组件中的store是靠props传进去的,而不是在容器组件中直接引入

  • 备注2:mapDispatchToProps也可以是一个对象

  • 注意:详细代码见gitee

7.5react-redux的优化

  • 简写mapDispatch

  • Provider组件的使用

  • 整合UI组件与容器组件

    • 容器组件和UI组件组合成一个文件

    • 无需自己给容器组件传递store,给<App/>包裹一个<Provider store={store}>即可。

    • 使用了react-redux后也不用再自己检测redux中状态的改变了,容器组件可以自动完成这个工作。

    • mapDispatchToProps也可以简单的写成一个对象

    • 一个组件要和redux“打交道”要经过哪几步?

      • 定义好UI组件—不暴露

      • 引入connect生成一个容器组件,并暴露,写法如下:

        connect(
        state =>({key:value})
        {key : xxxxxAction}
        )(UI组件)
        
    • 在UI组件中通过this.props.xxxxxxx读取和操作状态

  • 注意:详细代码见gitee

7.6数据共享

  • 定义一个Pserson组件,和Count组件通过redux共享数据

  • 为Person组件编写: reducer、action,配置constant常量。

  • 重点: Person的reducer和Count的Reducer要使用combineReducers进行合并,合并后的总状态是一个对象!!!

  • 交给store的是总reducer,最后注意在组件中取出状态的时候,记得“取到位”。

  • 注意:详细代码见gitee

7.7纯函数

  • 一类特别的函数:只要是同样的输入(实参),必定得到同样的输出(返回)
  • 必须遵守以下一些约束
    • 不得改写参数数据
    • 不会产生任何副作用,例如网络请求,输入和输出设备
    • 不能调用Date.now)或者Math.random()等不纯的方法
  • redux的reducer函数必须是一个纯函数

7.8redux开发者工具

  • 首先在Google浏览器中下载扩展程序Redux DevTools

  • 安装:终端输入npm i redux-devtools-extension

  • store中进行配置

    import {composewithDevTools} from 'redux-devtools-extension'
    const store =createStore(allReducer,composelithDevTools(applyMiddleware(thunk)))
    

7.9最终版

  • 所有变量名字要规范,尽量触发对象的简写形式。
  • reducers文件夹中,编写index.js专门用于汇总并暴露所有的reducer
  • 注意:详细代码见gitee

7.10项目打包

  • 打包:npm run build
  • 下载插件:npm i serve -g
  • 启动:serve build
  • 注意:在实际开发中,需要把build交给后端人员,再由后端人员配置到服务器中。

相关文章:

前端学习--React部分

文章目录 前端学习--React部分前言1.React简介1.1React的特点1.2引入文件1.3JSX&#x1f349;JSX简介与使用&#x1f349;JSX语法规则 1.4模块与组件&#x1f349;模块&#x1f349;组件 1.5安装开发者工具 2.React面向组件编程2.1创建组件&#x1f349;函数式组件&#x1f349…...

24V_2A_1.2MHZ|PCD0303升压恒频LCD背光源专用电路超小体积封装

概述 PCD0303是一个恒定频率&#xff0c;6针SOT23电流模式升压转换器用于小型低功耗应用。PCD0303 以1.2MHz切换&#xff0c;并且允许使用微小的&#xff0c;低成本电容器和电感器2mm或更小,内部软启动会产生较小的涌入电流延长电池寿命。PCD0303具有自动切换至轻负载下的脉冲…...

python生成词云图

生成词云图的话需要先对数据进行分词处理 , 分词方法点击查看 import pandas as pd from collections import Counter from wordcloud import WordCloud import matplotlib.pyplot as plt# 假设您已经按照之前的步骤处理了数据&#xff0c;并且处理后的数据保存在comments_proc…...

【使用ChatGPT构建应用程序】应用程序开发概述:1. 管理秘钥、2. 数据安全、3. 与应用程序解耦、4. 注意提示语的注入攻击

文章目录 一. 首先注意的两个方面1. 管理API密钥1.1. 用户提供API密钥1.2. 你自己提供API密钥 2. 数据安全和数据隐私 二. 软件架构设计原则&#xff1a;与应用程序解耦三. 注意LLM提示语的注入攻击1. 分析输入和输出2. 监控和审计3. 其他要注意的注入情况 在了解了ChatGPT的文…...

【JavaScript脚本宇宙】不可或缺的Web开发工具:图表和可视化

图形化你的数据&#xff1a;六款顶级JavaScript库全接触 前言 在本文中&#xff0c;我们将深入探讨六个强大的JavaScript库&#xff0c;这些库被广泛应用于数据可视化和交互式图形展示。我们将了解每个库的概述、主要特性、使用示例以及使用场景&#xff0c;以帮助读者更全面…...

自然语言处理(NLP)中的迁移学习

Transfer Learning in NLP 迁移学习&#xff08;Transfer Learning&#xff09;无疑是目前深度学习中的新热点&#xff08;相对而言&#xff09;。在计算机视觉领域&#xff0c;它已经应用了一段时间&#xff0c;人们使用经过训练的模型从庞大的ImageNet数据集中学习特征&…...

PLC集成BL121PO网关优化智能电网的远程管理PLC转OPC UA协议

随着工业自动化技术的不断发展&#xff0c;智能电网等复杂系统对于设备之间高效通信的需求日益增加。PLC转OPC UA协议转换网关BL121PO作为一款领先的协议转换设备&#xff0c;通过其独特的设计和功能&#xff0c;为用户提供了高效、安全的PLC接入OPC UA的解决方案。 设备概述 …...

爬虫案例(读书网)

一.我们还是使用简单的bs4库和lxml&#xff0c;使用xpath&#xff1a; 导入下面的库&#xff1a; import requests from bs4 import BeautifulSoup from lxml import etree 我们可以看见它的div和每个书的div框架&#xff0c;这样会观察会快速提高我们的简单爬取能力。 二.实…...

Linux系统编程(五)多线程创建与退出

目录 一、基本知识点二、线程的编译三、 线程相关函数1. 线程的创建&#xff08;1&#xff09;整型的传入与接收&#xff08;2&#xff09;浮点数的传入与接收&#xff08;3&#xff09;字符串的传入与接收&#xff08;4&#xff09;结构体的传入与接收 2. 线程的退出3. 线程的…...

计算机毕业设计 | SpringBoot个人博客管理系统(附源码)

1&#xff0c;绪论 1.1 背景调研 在互联网飞速发展的今天&#xff0c;互联网已经成为人们快速获取、发布和传递信息的重要渠道&#xff0c;它在人们政治、经济、生活等各个方面发挥着重要的作用。互联网上发布信息主要是通过网站来实现的&#xff0c;获取信息也是要在互联网中…...

字母的大小写转换

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 在Python中&#xff0c;字符串对象提供了lower()方法和upper()方法进行字母的大小写转换&#xff0c;即可用于将大写字母转换为小写字母或者将小写字…...

JTW结构

JTW(JSON Web Token)的结构 在这篇笔记中,我们将了解JTW(JSON Web Token)的结构。我们将看到JTW是如何创建的,令牌的各个部分是什么,以及您如何自己构建和构造JTW。您还将了解一些这种结构的含义,以及使用JTW进行授权时的一些结果优缺点。 基本上,JTW本质上就是一个…...

debian11安装留档@VirtualBox

因为debian12无法安装tpot&#xff0c;所以又把11重新安装一遍&#xff0c;以前的安装文档&#xff1a;安装Debian 11 留档-CSDN博客 下载光盘 华为云地址&#xff1a;https://repo.huaweicloud.com/debian-cd/11.0.0/amd64/iso-cd/ 使用了debian11 教育版&#xff0c;比较有…...

SpringBoot——整合Thymeleaf模板

目录 模板引擎 新建一个SpringBoot项目 pom.xml application.properties Book BookController bookList.html ​编辑 项目总结 模板引擎 模板引擎是为了用户界面与业务数据分离而产生的&#xff0c;可以生成特定格式的页面在Java中&#xff0c;主要的模板引擎有JSP&…...

电商推荐系统+电影推荐系统【虚拟机镜像分享】

电商推荐系统电影推荐系统【虚拟机镜像分享】 所有组件部署好的镜像下载&#xff08;在下面&#xff09;&#xff0c;仅供参考学习。&#xff08;百度网盘&#xff0c;阿里云盘…&#xff09; 博主通过学习尚硅谷电商推荐电影推荐项目&#xff0c;将部署好的虚拟机打包成ovf文…...

(函数)判断素数(C语言)

一、运行结果&#xff1b; 二、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>//声明素数判断函数&#xff1b; void prime(int number);int main() {//初始化变量值&#xff1b;int number 0;//获取用户输入的数据&#xff1b;printf(&quo…...

git 学习随笔

git 学习随笔 基本概念 git 对待数据类似快照流的形式而不是类似 cvs 那样的纪录文件随时间逐步积累的差异 git 中所有数据在存储钱都会计算校验和&#xff08;hash) 三种状态&#xff1a;已提交(committed)&#xff0c;已修改(modified)&#xff0c;已暂存(staged)。 add…...

【因果推断python】1_因果关系初步1

目录 为什么需要关心因果关系&#xff1f; 回答不同类型的问题 当关联确实是因果时 为什么需要关心因果关系&#xff1f; 首先&#xff0c;您可能想知道&#xff1a;它对我有什么好处&#xff1f;下面的文字就将围绕“它”展开&#xff1a; 回答不同类型的问题 机器学习目…...

(函数)颠倒字符串顺序(C语言)

一、运行结果&#xff1b; 二、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h> # include <string.h>//声明颠倒函数; void reverse(char a[]) {//初始化变量值&#xff1b;int i, j;char t;//循环颠倒&#xff1b;for (i 0, j strl…...

自定义数据集上的3D目标检测:使用OpenPCDet训练CenterPointPillar模型

前言 在自动驾驶和机器人领域&#xff0c;3D目标检测是关键技术之一。它能够提供关于周围环境中物体的精确位置和尺寸信息。OpenPCDet是一个基于PyTorch的开源3D目标检测框架&#xff0c;支持多种3D检测网络。在本文中&#xff0c;我们将探讨如何使用OpenPCDet框架和CenterPoi…...

音乐传奇告别之作:《杰作》未解之谜❗❗

坂本龙一的《杰作》不仅是一部音乐会纪录电影&#xff0c;更是他赠予世界的一封深情告别信。 这部影片精心收录了这位音乐巨匠生前最后一场钢琴独奏音乐会的珍贵瞬间&#xff0c; 其中涵盖了《圣诞快乐&#xff0c;劳伦斯先生》、《末代皇帝》、《水》等二十首令人陶醉的经典…...

【Postman接口测试】第四节.Postman接口测试项目实战(上)

文章目录 前言一、项目介绍 1.1 项目界面功能介绍 1.2 项目测试接口介绍 1.3 项目测试接口流程二、HTTP协议三、接口测试中接口规范四、项目合同新增业务介绍 4.1 登录接口调试 4.1 登录接口自动关联 4.1 添加课程接口调试 4.1 上传合同…...

opencv学习备份

2019年3月9日 指针地址向后走 int a[5] {1,100,200,300} int *pa –>*p1 –>*p100 指针移动 –> p0x00000000 内存地址 int a1 int *p&a 指针赋值常量&#xff0c;需要加寻址符号 –>*p1 –>*p CV_8UC1&#xff0c;CV_8UC2&#xff0c;CV_8UC3。 (最后的…...

Unity 中获取调用者方法名

介绍 在 Unity 开发中&#xff0c;有时需要在代码中获取当前方法的调用者方法名&#xff0c;以便进行日志记录、调试等操作。本教程将详细介绍如何使用 C# 中的 StackTrace 类来实现这一功能&#xff0c;并将其封装成一个便捷的工具类&#xff0c;以方便在项目中的任何地方…...

k8s集群中pod的容器资源限制和三种探针

一、资源限制 总结&#xff1a; requests表示创建pod时预留的资源&#xff0c;limits表示pod能够使用资源的最大值。requests值可以被超&#xff0c;limits值不能超过&#xff0c;如果是内存使用超过limits会触发oom然后杀掉进程&#xff0c;如果是cpu超过limits会压缩cpu的使用…...

tar 详细说明

tar命令在Unix和类Unix系统中被广泛用于打包和压缩文件。以下是对tar命令的详细说明&#xff1a; 一、命令概述 tar命令的名称来源于“tape archive”&#xff08;磁带存档&#xff09;&#xff0c;最初设计用于在磁带上创建备份。现在&#xff0c;它已成为在Unix和类Unix系统…...

渗透测试工具Cobalt strike-2.CS基础使用

三、结合metasploit,反弹shell 在kali中开启使用命令开启metasploit msfconsole ┌──(root㉿oldboy)-[~] └─# msfconsole --- msf6 > use exploit/multi/handler [*] Using configured payload generic/shell_reverse_tcp --- msf6 exploit(multi/handler) > show …...

【UE5.1 角色练习】08-物体抬升、抛出技能 - part2

目录 前言 效果 步骤 一、让物体缓慢的飞向手掌 二、向着鼠标方向发射物体 前言 在上一篇&#xff08;【UE5.1 角色练习】08-物体抬升、抛出技能 - part1&#xff09;的基础上继续完成角色将物体吸向手掌&#xff0c;然后通过鼠标点击的方向来发射物体的功能。 效果 步骤…...

Java面试题--JVM大厂篇(1-10)

引言&#xff1a; 在这个信息时代&#xff0c;对于准备进入大厂工作的朋友们来说&#xff0c;对于JVM&#xff08;Java虚拟机&#xff09;的掌握是面试中的一项重要内容。下面是一些精选的JVM面试题&#xff0c;希望对大家能有所帮助。 正文&#xff1a; 1. JVM有哪几种垃圾收…...

【知识拓展】机器学习基础(一):什么是预处理对象、模型对象 、pipeline、Tokenizer

前言 公司业务需要一套可离线部署的检索增强生成(RAG)大模型知识库&#xff0c;于是最近花了一周时间了解了AI相关的技术。除了查阅各类高质量技术博客&#xff0c;也自行动手进行了一些demo样例。其中包括huggingface、modelscope等平台&#xff0c;虽能使用&#xff0c;但疑惑…...