股票做空网站/推广引流哪个软件最好
文章目录
- react学习笔记01
- 入门
- 概述
- React 基础案例HelloWorld
- 三个API介绍
- JSX
- JSX 解构数组
- 创建react项目(手动)
- 创建React项目(自动) | create-react-app
- 事件处理
- React中的CSS样式
- 内联样式 | 内联样式中使用state (不建议使用)
- 外部样式表 | CSS Module
- React组件
- 函数式组件和类组件
- 生成一组标签/组件
- props 父组件给子组件传属性/方法
- 给组件设置className样式不生效
- state 维护组件的响应式状态
- useState(stateInitValue)
- Ref 获取DOM对象
- 非受控组件与受控组件
- 数据的双向绑定
- 子组件给父组件传值 = props传递函数 + 子组件调用函数
- vue中v-if与v-show的React写法
- Portal 将元素渲染到指定位置
- Fragment 组件
- Context 祖先组件向子孙组件传值
- Effect 副作用
- setState()在函数组件中的执行流程
- React.StrictMode
react学习笔记01
学习视频 react18 李立超
学习中get到的新用法
-
Date
类的toLocalString
方法,可以更为灵活的处理Date
类。 -
标签属性中闭包的使用
举例:仅在删除状态时使用id,不需要单独传递id属性。const logItemDate = logsData.map(item=> <LogItem onDelLog ={()=> delLog(item.id)}>)
-
移动端适配
rem + vw
可以使用vw
获取视口宽度,将font-size
设置单位为vw
,然后结合rem
做适配。
1vw = 视口宽度的1%
->100vw = 视口的宽度
一般设置
html的font-size值 = 屏幕宽度/设计稿宽度
,但移动端比如375px
计算出的font-size
值小于12px
会造成一些错误和奇怪的问题,因此把比例扩大100倍
。为了使比例不变,相应的设计图元素使用时
设计图元素大小/100 rem
根html的font-size值 = 屏幕宽度/设计稿宽度*100 font-size = 100vw/设计稿宽度*100
入门
概述
AJAX+DOM
可以实现网页的局部刷新,但是新数据不能直接在网页中显示,需要通过DOM将数据转换为网页中的节点。
react
帮助我们根据不同的数据来快速构建用户项目,同时在构建过程中确保其流畅度。
react
特点
1.使用虚拟DOM而不是真正的DOM
2.声明式编码(声明式:结果为导向,不关心结果 命令式:一行代码一个命令)
3.支持服务器端渲染
React 基础案例HelloWorld
入门案例采用外部引入脚本使用(正常开发使用包管理器)
react.development.js
react
是react
核心库,只要使用react
就必须要引入。下载地址react-dom.development.js
react-dom
是react
的dom
包,使用react
开发web
应用时必须引入。下载地址babel.min.js
浏览器不能识别JSX
,利用该babel
将JSX
转换为JS
代码。下载地址
1.引入脚本
<script src="../script/react.development.js"></script>
<script src="../script/react-dom.development.js"></script>
2.创建一个React
元素
React.createElement(组件名/元素名,元素中的属性,元素的子元素/内容)
const reactDiv = React.createElement('div',{},'我是react创建的div');
3.获取根元素对应的React
元素
ReactDOM.createRoot(Dom元素);
// html
<div id="root"></div>
// js
const root = ReactDOM.createRoot(document.getElementById('root'));
4.将reactDiv
渲染到React
根元素中
root.render(reactDiv)
三个API介绍
-
React.createElement(type,[props],[...children])
用来创建React
元素(并不是ReactDom
,所以这里使用React
调用)-
class
属性需要使用className
属性代替。 -
type
如果是标签名(元素)需要全小写,首写母大写会被认为是组件 -
在设置属性时,事件名应遵守驼峰命名法,事件值需要是一个函数,不能是
console.log(xx)
这种表达式。如果直接写一个函数调用语句,则在绑定事件时就会被调用(之后事件不会被触发) -
React元素是一次性的,一旦创建就无法修改,只能使用新创建的元素进行替代
-
-
ReactDOM.createRoot(container[,options]);
用来创建React的根容器,根容器用来放置React
元素- 将参数的
DOM
元素转换为React
根元素
- 将参数的
-
ReactDOM实例.render(ReactElement)
将React
元素渲染到根元素中DOM
根元素中所有的内容都会被删除(不会修改DOM
根元素本身),被React
元素转换而成的DOM
元素替换- 重复调用
render()
,React会将两次虚拟DOM
进行对比,确保只修改发生变化的元素,对DOM做最少修改。首次调用时,容器节点里的所有DOM都会被替换,后续的调用则会使用React
的DOM
差分算法(diff
)进行更新
JSX
上述方法中React.createElement('button', {}, '我是按钮')
还是命令式编码方法,告诉react
用createElement
去创建一个button
按钮,该按钮没有属性,内容为我是按钮。
声明式编程结果导向,告诉结果,不关系过程怎么样。
const button = <button>我是按钮</button>; // 告诉react我需要一个button按钮元素,不关心react如何创建
在React
中可以通过JSX
(JavaScript Syntax Extension
)来创建React
元素,JSX
让我们以类似于HTML
的形式去使用 JS
。JSX
是React
中声明式编程的体现方式。
JSX
需要被翻译为JS
代码,才能被React
执行。 要在React中使用JSX
,必须引入babel
来完成“翻译”工作。
-
JSX
就是React.createElement()
的语法糖,最终都会转换为以调用React.createElement()
创建元素的代码。 -
JSX
在执行之前都会被babel
转换为JS
代码<!-- 引入babel --> <script src="script/babel.min.js"></script> <!--设置js代码被babel处理--> <script type="text/babel">const div = <div>我是一个div<button>我是按钮</button></div>;const root = ReactDOM.createRoot(document.getElementById('root'));root.render(div); </script>
-
JSX
不是字符串,不需要加引号
const div = <div>我是一个div</div> // 正确写法
JSX
中html
标签应该小写开头,React
组件应该大写开头
<div> // 小写html标签
<Div> // 大写组件
-
JSX
有且只有一个根标签 -
JSX
的标签必须正常结束(自结束标签必须写/
)
const input = <input type="text" / >
- 在
JSX
中使用{}
嵌入表达式(有值的语句就是表达式)
const name = "ranran"
const div = <div>{name}</div> // 才会显示ranran,没有括号会把name识别为字符串
-
如果表达式值为空值、布尔值、undefined,将不会显示
-
在
JSX
属性可以直接在标签中设置- 事件绑定需要是一个函数,而不能直接是函数调用(绑定时就会被触发,不会延迟触发)
className
代替class
style
必须使用对象设置,属性名必须用驼峰命名法
const div = <div onClick="()=>{console.log('ranran')}" style={{backgroundColor: "yellowgreen", border: '10px red solid'}}
></div> // 外面的大括号表示style必须使用对象设置,里面的对象表示给他设置的值是一个对象(有多个样式)
-
在语句中可以操作
JSX
const name = 'ranran'; const lang = 'cn';let div; if(lang === 'en'){div = <div>hello {name}</div>; }else if(lang === 'cn'){div = <div>你好 {name}</div>; } const root = ReactDOM.createRoot(document.getElementById('root')) root.render(div)
JSX 解构数组
JSX在解构{}
的内容时,如果内容是数组则会自动将其展开。
//页面:孙悟空猪八戒沙和尚
const data = ['孙悟空', '猪八戒', '沙和尚'];
const div = <div>{data}</div>
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(div)/*
· 孙悟空
· 猪八戒
· 沙和尚
*/
const data = ['孙悟空', '猪八戒', '沙和尚'];
const list = <ul>{data.map(item => <li>{item}</li>)}</ul>;
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(list)//页面:孙悟空猪八戒沙和尚
const data = ['孙悟空', '猪八戒', '沙和尚'];
const div = <div>{data}</div>
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(div)/*
· 孙悟空
· 猪八戒
· 沙和尚
*/
const data = ['孙悟空', '猪八戒', '沙和尚'];
const list = <ul>{data.map(item => <li>{item}</li>)}</ul>;
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(list)
React通过虚拟DOM
将React
元素和原生DOM
元素进行映射
当我们调用root.render时。页面就会发生重新渲染
React通过diff
算法将新的虚拟DOM和旧的比较,找到发生变化的元素,并且只对变化的元素进行修改。
数组中(当前数组)每一个元素都需要设置一个唯一key
值
重新渲染页面时,React
有key
值会比较key
值相同的元素,没key
值会按照顺序进行比较。
- 开发中一般会采用数据的
id
作为key
- 尽量不使用元素的
index
作为key
索引会跟着元素顺序的改变而改变,所以使用索引做key
跟没有key
是一样的。 唯一的不同就是,控制台的警告没了。 当元素的顺序不会发生变化时,用索引做key
也没有什么问题。
const data = ['孙悟空', '猪八戒', '沙和尚'];
const list = <ul>{data.map(item => <li key={ item }>{ item }</li>)}</ul>;
// const list = <ul>{data.map((item,index) => <li key={ index }>{ item }</li>)}</ul>;
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(list)
创建react项目(手动)
React
官方为了方便开发,提供react-scripts
包(①打包②测试服务器-根据代码变化自动刷新避免改一点就重新打包),包中提供了项目开发中的大部分依赖。
由于提供了配置好的工具,我们一些操作就要符合约定。
使用包管理器管理项目,没有办法直接放在网页中运行。需要经过webpack打包,才能在浏览器中正常执行。
- 创建
React
根目录- public(可以web直接访问的文件,不用打包就可以浏览器访问的静态资源)- index.html (入口文件,必须有,首页模板打包时以此为模板生成最终的index/html | 添加标签 <div id="root"></div>)- src(源码,JS源代码)- index.js(必须,webpack打包文件的入口,该文件会被自动引入public/index.html中)
pnpm init
初始化项目,生成package.json
文件(大部分时候这一步可以省略)pnpm install react react-dom react-scripts
安装项目依赖- 编写代码
src/index.js
// 引入ReactDOM
import ReactDOM from 'react-dom/client';// 创建一个JSX
const APP = <div><h1>这是一个react项目</h1></div>// 获取一个根元素
const root = ReactDOM.createRoot(document.getElementById('root'));
// 将APP渲染进根容器
root.render(APP);
- 运行项目
pnpm react-scripts build
打包项目,一般开发完成之后需要上线时使用该命令进行打包。
初次需要输入y确认。打包时需要默认配置,会询问是否添加默认配置。
正常情况,右键打开会报错。因为打包好的文件需要部署在服务器上运行,而不是直接使用浏览器打开。每次打包后路径都是这样需要手动修改。
-
pnpm react-scripts start
开发中使用的命令
通过webpack
启动内部的测试服务器,可以实时对更新代码进行编译。这个命令太长,可以在package.json
的scripts
选项中配置命令,下次可以使用命令pnpm start
。"scripts": {"start": "react-scripts start" }
react 一定需要两个文件
public/index.html
:入口文件,首页模板打包时以此为模板生成最终的index/html
- 提供dom root
根节点src/index.js
:webpack
打包文件的入口,该文件会被自动引入public/index.html
中 - 将root转化为react根节点元素后,将react元素挂载到react根节点中
创建React项目(自动) | create-react-app
命令:npx create-react-app 项目名
除了public/index.html
和src/index.js
必须保留外,其他的东西都是可以删除的。
/*reate-react-app 创建index.js其中<React.StrictMode>使用严格模式渲染React元素 - 可以不使用
*/
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<React.StrictMode>aaa</React.StrictMode>
);
事件处理
react
元素的事件处理和 DOM
元素的很相似,但是有一点语法上的不同:
-
React
事件的命名采用小驼峰式(camelCase
),而不是纯小写。 -
使用
JSX
语法时需要传入一个函数作为事件处理函数。事件绑定需要是一个函数,而不能直接是函数调用(绑定时就会被触发,不会延迟触发,等于将函数的返回值给了该事件)// 传统 HTML <button onclick="activateLasers()">Activate Lasers </button> // React <button onClick={activateLasers}> Activate Lasers </button>
-
React
事件通过会传递事件对象event
,但其不同于原生的事件对象,是React
包装后的事件对象,该对象已经处理了跨浏览器的兼容性问题。React
中事件回调函数不能通过返回false
阻止默认行为,必须显式地使用event
事件对象的preventDefault
方法// 传统 HTML<form οnsubmit="console.log('You clicked submit.'); return false"><button type="submit">Submit</button> </form>// React function Form() {function handleSubmit(e) {e.preventDefault(); console.log('You clicked submit.');}return (<form onSubmit={handleSubmit}><button type="submit">Submit</button></form>); }
React中的CSS样式
内联样式 | 内联样式中使用state (不建议使用)
style
必须使用对象设置,属性名必须用驼峰命名法
const StyleDemo = () => {return (<div style={{color:'red', backgroundColor:'#bfa', fontSize:20, borderRadius:12}}>我是Div</div>);
};export default StyleDemo;
当样式过多,JSX
会比较混乱,可以使用变量去保存对象
import React from 'react';const StyleDemo = () => {const divStyle = {color: 'red', backgroundColor: '#bfa', fontSize: 20, borderRadius: 12}return (<div style={divStyle}>我是Div</div>);
};export default StyleDemo;
内联样式中使用state
当样式是动态时,可以在样式中使用state变量。
import React, {useState} from 'react';const StyleDemo = () => {const [showBorder, setShowBorder] = useState(false);const divStyle = {color: 'red',backgroundColor: '#bfa',fontSize: 20,borderRadius: 12,border: showBorder?'2px red solid':'none'};const toggleBorderHandler = ()=> {setShowBorder(prevState => !prevState);};return (<div style={divStyle}>我是Div<button onClick={toggleBorderHandler}>切换边框</button></div>);
};export default StyleDemo;
外部样式表 | CSS Module
外部样式是指将样式编写到外部的css
文件中,直接通过import
引用。
直接import引入的样式都是全局样式,其他组件也看得见这个样式。如果不同的样式表中出现了相同的类名,会出现相互覆盖情况。
import './index.css'
CSS Module
使用CSS Module
后,网页中元素的类名会自动计算生成并确保唯一。
如果引用同一个模块,计算出来的类名是相同的。
CSS Module
在React
中已经默认支持(前提是使用了react-script
)
- 文件样式的文件名为
xxx.module.css
- 在组件中引入样式的格式为
import xxx from './xxx.module.css'
- 设置类名时通过
xxx.yyy
的形式来设置
/*
StyleDemo.module.css
*/
.myDiv{color: red;background-color: #bfa;font-size: 20px;border-radius: 12px;
}/*
StyleDemo.js
*/
import Styles from './StyleDemo.module.css';const StyleDemo = () => {return (<div className={Styles.myDiv}>我是Div</div>);
};export default StyleDemo;
React组件
组件需要遵守的规则
- 组件名首字母必须大小(小写字母开头的组件会被视为原生DOM标签)
- 组件中只能有一个根元素
函数式组件和类组件
React
中定义组件有两种方式
- 基于函数的组件 - 函数式组件(推荐) :函数组件是返回
JSX
普通函数 - 基于类的组件 - 类组件
函数式组件
函数组件是返回JSX
普通函数
//1.创建函数式组件 App.js
const App = () => {return <div>我是App组件!</div>
};
// 2.导出App
export default App;// index.js
// 3.引入App
import App from "./App";
const root = ReactDOM.createRoot(document.getElementById('root'));
// 4.React组件可以直接通过JSX渲染
root.render(<App/>); //root.render(App()); 也可以,只是<App/>内部做了更多的事情。
类组件
1.创建一个ES6 class
,并继承于React.Component
2.添加一个render
方法,方法的返回值为JSX
import React from "react"
//1.创建类组件 必须要继承React.Component
class App extends React.Component{constructor(props){ // 参数props接受父组件的传值this.state = 'xxx' //state的使用}// 2.添加render方法render(){return <div>我是一个类组件{this.props}</div>}
}// index.js
// 3.引入App
import App from "./App";
const root = ReactDOM.createRoot(document.getElementById('root'));
// 4.React组件可以直接通过JSX渲染
root.render(<App/>); //root.render(App()); 也可以,只是<App/>内部做了更多的事情。
props、state、ref
-
类组件的
props
存储在类的实例对象中,可以通过this.props
访问。 -
类组件中
state
统一存储到了实例对象的state属性中,可以通过this.state
来访问,通过this.setState()
修改。- 通过
this.setState
修改state
,只修改设置了state
的属性,并不会修改没设置的第一层属性。
- 通过
-
通过
React.createRef()
(函数式为useRef)创建属性存储DOM对象,同样通过对象.current
获取 -
事件回调函数需要定义为类的方法,建议使用箭头函数,这样
this
指向的是react
实例。否则函数里的this会执行设置事件的dom
元素
import React,{ Component } from 'react'class App extends Component{state = {count:0,age:{} } divRef = React.createRef();// 事件回调函数需要定义为类的方法,建议使用箭头函数,这样this指向的是react实例。否则函数里的this会执行设置事件的dom元素clickHandler = ()=>{// 写法1:this.setState({count:this.state.count+1})// 写法2this.setState(prevCount => {return {count:prevCount+1;}})}retnder(){return <div><h1 ref={ divRef }>this.props<h1><h1 @onClick={this.clickHandler}>this.state.count<h1> </div>}
}
生成一组标签/组件
在react
中对于根据数组数据产生一组标签或者一组组件,没有类似vue
的v-for
指令,一般使用{ data.map(JSX) }
的语法进行生成。
const App= () => {const data = [{title:"1",id:"0"},{title:"2",id:"1"},{title:"3",id:"2"}];return <div>{ data.map(item => <Button key={item.id} titile={item.title}></Button >) }</div> /*写法1 return <div> { data.map(item => <Button key={item.id} titile={item.title} />) } </div> 写法2:将对象的每个属性都传递return <div> { data.map(item => <Button {...item}>) </div>}*/
};export default App;
props 父组件给子组件传属性/方法
父组件通过使用子组件时,定义自定义参数传递属性/方法。子组件通过参数props
接收(函数式组件的第一个参数)。
react
中的props
类似vue
中的props
,是只读属性是无法修改的
props.children
中可以获取到父组件中,子组件标签体内部的值。
// 父组件
<Button bgColor='red' color={ color }>我是一个按钮</Button>//子组件
const Button = (props) => {return <button style={{backgroundColor:props.bgColor, color:props.color}}>{props.children}</button>;
};export default Button;
给组件设置className样式不生效
原因
className
会被认为是一个属性传递给子组件,需要在子组件的根元素使用className={props.className}
接收。
state 维护组件的响应式状态
在React
中,当组件渲染完毕后,再修改组件中的变量,不会使组件重新渲染。state
相当于一个变量,只不过在React
中进行了注册。React
会监控整个变量的变化,当state
发生变化时,会自动触发组件的重新渲染。
页面的渲染靠的是
render
函数
state概述
state
与props
类似,都是一种存储属性的方式。
- state只属于当前组件(组件的私有属性),其他组件无法使用。
- state的值是对象,当其内容发生变化相关组件会一起刷新
useState(stateInitValue)
通过钩子函数useState(stateInitValue)
创建state
,React
中钩子函数只能用于函数组件或自定义钩子。
- 参数是整个
state
变量的初始值 - 函数返回一个数组
[stateVariable,setStateFunction]
,第一个元素是state
变量的初始值(只用于显示),第二个元素是修改该变量的函数(函数的参数为新值)。调用修改函数修改state
变量的值(state值发生变化)会触发组件的重新渲染,直接修改state变量不会触发组件的重新渲染。
import { useState } from 'React'const [stateVariable,setStateFunction] = useState(1);
注意点
- 当
state
值是一个对象时,setState()
修改时,使用新的对象去替换已有对象。
const [user, setUser] = useState({name:"ranran",age:18})
user.name = "xxx";
serUser(user); // user是对象,对象的地址没有发生变化,所以不会引起组件重新渲染/*
解决方案:将其拷贝给另一个新对象,修改新对象的属性
*/
setUser({...user,name:"xxx"}) // 后面的name会覆盖前面的name
-
通过
setState()
去修改一个state
时,并不表示修改当前的state
,修改的是组件下一次渲染的state
-
setState()
会触发组件的异步渲染(并不是马上调用就渲染,放入事件循环队列中等待执行),所以当调用setState()
需要使用state值时,可能出现计算错误。因为
setState()
修改的是下一次渲染的state
,如果下一次渲染还没进行前又调用了setState()
,此时state
还是旧值,所以就会出现计算错误。解决办法 : 通过传递回调函数的形式修改
state
回调函数的返回值会成为新的state值,回调函数执行时
React
会将最新的state
值作为参数传递。setCount(state => state+1); // 传递参数,React会保证参数的state是最新值
如果setState()
中需要用到旧值,参数都采用函数的形式。
Ref 获取DOM对象
Ref
是reference
的简写,用来获取真实DOM
的引用。
- 使用
useRef()
钩子函数获取DOM
对象- 1.通过
useRef()
钩子函数返回一个普通JS对象,React
会自动将DOM
对象传递到该对象的current
属性中。 - 2.被引用的DOM元素上添加
ref
属性,值为上述的对象。
根据描述,直接创建一个有current
属性的普通JS
对象可以实现相同的效果。
- 1.通过
两种方法的不同点
- 自定义对象方法,组件每次重新渲染,都会创建一个新对象
- 使用
useRef()
函数返回的对象的声明周期和组件的声明周期一致,所以每次重新渲染,该ref
对象都是原来的。
import {useRef} from 'react';const MyComponent = () => {const divRef = useRef();/*const divRef = {current:null}*/const clickHandler = () => {console.log(divRef);};return (<div ref={divRef} onClick={clickHandler}>一个div</div> );
};export default MyComponent;
非受控组件与受控组件
非受控组件:表单中的数据来源于用户填写的组件,表单元素的值不会更新state,输入数据都是现用现取的。
受控组件:使 React
的 state
成为唯一数据源,由state
控制表单。
数据的双向绑定
将表单的value
绑定为state
数据,表单的onChange
事件触发时,通过事件对象event
获取到新值,然后使用setState
修改state
的值为新值。
import { useState } from 'react';
import './index.css';const Demo = () => {// 如果有多个表单,可以将表单数据设置为一个对象const [inputValue, setInputValue] = useState('');return (<><inputtype="text"className="inputDemo"value={inputValue}onChange={e => {setInputValue(e.target.value);}}/></>);
};export default Demo;
子组件给父组件传值 = props传递函数 + 子组件调用函数
- 在父组件中,使用
props
给子组件传递一个自定义事件 - 在子组件中将需要传递的数据作为函数参数,调用函数
// 父组件
<LogsItem onSavaLog={ savaLogHandler }>// 子组件
const LogsItem = (props) => {props.savaLogHandler("需要传递的数据");
}
关于传递
setState
函数给子组件的一些说法:尽量不要这样做,state
在哪里,setState
尽量就在哪里。
vue中v-if与v-show的React写法
v-if
-v-else
配对出现 可以使用条件判断v-show
/仅有v-if
可以使用&&
// v-if/v-else 可以使用条件判断
控制变量 ? v-if显示的 : v-else显示的// v-show/仅有v-if 可以使用&&
控制变量 && v-show显示的
如果显示出来的组件内部需要修改外部的控制变量,
react
中一般的做法时将函数作为参数传递。因为控制变量在外部,内部只需要调用该函数,外部修改控制变量的值。
Portal 将元素渲染到指定位置
在React
中,父组件引入子组件后,子组件会直接在父组件内部渲染。换句话说,React
元素中的子组件,在DOM
中,也会是其父组件对应DOM
的后代元素。
问题描述
每个组件都是相同的构成(想象成一个列表),组件内部包含一个子组件,该子组件的作用是生成一个遮罩覆盖全局。
组件1开启相对定位,遮罩开启固定定位(不一定是和这个例子相同的定位方式,这里举例)
由于组件1组件2组件3的 z-index:1
,后面的组件会覆盖前面的。所以组件1中的遮罩出现时,覆盖不了组件2组件3,即使遮罩的z-index:999
(理解为在组件1内部元素的层级中占比很高,但不影响组件1的层级),但组件1和其他兄弟组件层级相同(父元素组件1都被覆盖了子元素肯定被一起覆盖)。
结构问题:遮罩需要遮住视图不应该作为组件123的子组件,如果必须这样写,解决办法是使用Portal
将组件渲染到指定位置
ReactDOM.createPortal(需要渲染的元素,传送到的指定位置)
:渲染元素时将元素渲染到网页中的指定位置
1.在index.html
中添加一个新的元素
<div id="root"></div>
<!--这个容器用来专门渲染遮罩层-->
<div id="backdrop"></div>
2.在组件中通过ReactDOM.createPortal()将元素渲染到新建的元素中
const backdropDOM = document.getElementById('backdrop');// 在其他组件内部正常使用Backdrop组件,但是该组件渲染时会被传送到专门渲染遮罩层的容器中渲染,会脱离原来的结构
const Backdrop = () => {return ReactDOM.createPortal(<div>{props.children}</div>,backdropDOM);
};
Fragment 组件
在React
中,JSX
必须有且只有一个根元素,这导致在某些情况需要添加一个额外的父元素(并没有实际意义)
React
提供了Fragment
组件,Fragment
可以让你聚合一个子元素列表,并且不在DOM中增加额外节点<></>
是Fragment
的语法糖,<></>
语法不能接受键值或属性,但Fragment
可以传递key
属性
import React from 'react';const MyComponent = () => {return (<React.Fragment><div>我是组件1</div><div>我是组件2</div><div>我是组件3</div></React.Fragment>/*<><div>我是组件1</div><div>我是组件2</div><div>我是组件3</div></>*/);
};export default MyComponent;
Context 祖先组件向子孙组件传值
Context
相当于一个公共的存储空间
创建content
// defaultValue存储的值
export const MyContext = React.createContext({name:xxx,age:xxx,
});
访问到Context中的数据
-
方式1:通过
Consumer
标签来访问到Context
中的数据(不常用)该组件内部必须使用函数,解析时会调用该函数,将创建的
defaultValue
作为该函数的参数传递。import React from 'react'; import { MyContext } from '../store/test-context';const MyContext = () => {return (<MyContext.Consumer>{(ctx)=>{ // 上述案例中的defaultValuereturn (<ul><li>{ctx.name}</li><li>{ctx.age}</li></ul>);}}</MyContext.Consumer>); }; export default MyComponent;
-
方式2:使用钩子函数
useContext(context参数)
获取到context
,该钩子函数会返回Context
中的数据import React, {useContext} from 'react'; import { MyContext } from '../store/test-context';const MyComponent = () => {const ctx = useContext(MyContext);return (<ul><li>{ctx.name}</li><li>{ctx.age}</li></ul>); };export default MyComponent;
一般不会将数据直接放在Context
,因为这样写是死数据并且与state
响应式数据没什么关系,不会触发组件的重新渲染。所以React
还提供了Provider
组件,用于在数据所在的组件中指定Context
值。
import React from "react";
import MyComponent from "./component/MyComponent";
import { MyContext } from "./store/test-context";// 数据所在的组件
const App = () => {// 指定context的值return <MyContext.Provider value={{name:'猪八戒', age:28}}>/* Provider的子组件 */<MyComponent/> </MyComponent.Provider>;
};export default App;
Provider
设置在外层组件中,通过value
属性来指定Context
的值。这个Context
值在所有的Provider
子组件中都可以访问。Context
的搜索流程类似vue
的provide
和 inject
。
Effect 副作用
组件每次重新渲染,组件的函数体就会执行。
有一部分逻辑如果直接写在函数体中,会影响到组件的渲染,这部分会产生“副作用”的代码,是不能直接写在函数体中。
例如,如果直接将修改state的逻辑编写到了组件之中,每次函数体执行设置基础值,state变量又引起组件的更新,就会导致组件不断的循环渲染,直至调用次数过多内存溢出。
setState()在函数组件中的执行流程
setState()
会调用dispatchSetDate()
方法,dispatchSetDate()
方法的主要逻辑
-
判断组件当前处于什么阶段(渲染阶段 |非渲染阶段 )
-
处于渲染阶段:不会检查
state
值是否相同,在此时直接将setState
设置的值放入渲染队列等待渲染 -
处于非渲染阶段:检查
setState
设置的值与之前的值是否相同。如果值不同,对组件进行重新渲染;如果值相同,则不对组件进行重新渲染。
-
处于渲染阶段案例
const App = () => {const [count,setCount] = uesState(0);// 会触发Too many re-renders报错 // 调用的时候处于渲染阶段,因为div没有渲染到页面上,所以会引发重新渲染,再次调用组件函数。也就是说无限循环,不会退出渲染阶段。setCount(0); return (<div>{count}</div>)
}
处于非渲染阶段案例
第一次点击按钮count = 0 -> 1
,组件重新渲染。
第二次点击按钮count = 1 -> 1
,组件重新渲染。
第三次点击按钮count = 1 -> 1
,组件没有重新渲染。
这是因为当值相同时,React
在某些情况下(通常发生在值第一次相同时)会继续执行当前组件的渲染(这里指的时组件函数执行并更新页面),这次渲染不会产生实际效果(这里应该仅重新执行组件函数并不更新页面,不触发刷新没有什么用??)并且不会触发子组件的渲染。
const App = () => {const [count,setCount] = uesState(0);const clickHandler = ()=>{setCount(1); }return (<div onClick={ clickHandler }>{count}</div>)
}
React.StrictMode
脚手架自动生成的index.jx
中使用了该组件,该组件表示react
自身开启严格模式,开启后react
会自动去检查组件中是否有副作用的代码(并不是很智能)。
root.render(<React.StrictMode><App/></React.StrictMode>
)
React
的严格模式,在开发模式下,会主动重复调用一些函数,以使副作用出现。这些函数会被调用两次,如果安装了React Developer Tool
,调试作用的第二次调用会显示为黑色。
- 类组件的
constructor
,render
, 和shouldComponentUpdate
方法 - 类组件的静态方法
getDerivedStateFromProps
- 函数组件的函数体
- 参数为函数的
setState
- 参数为函数的
useState
,useMemo
,useReducer
相关文章:

react 学习笔记 李立超老师 | (学习中~)
文章目录 react学习笔记01入门概述React 基础案例HelloWorld三个API介绍 JSXJSX 解构数组 创建react项目(手动)创建React项目(自动) | create-react-app事件处理React中的CSS样式内联样式 | 内联样式中使用state (不建议使用)外部样式表 | CSS Module React组件函数式组件和类组…...

Docker镜像和容器的简单操作
1.镜像管理 搜索镜像: 这种方法只能用于官方镜像库 搜索基于 centos 操作系统的镜像 # docker search centos 按星级搜索镜像: 查找 star 数至少为 100 的镜像,默认不加 s 选项找出所有相关 ubuntu 镜像…...

章鱼网络进展月报 | 2023.11.1-11.30
章鱼网络大事摘要 1、2023年12月,Octopus 2.0 将会正式启动。 2、隐私协议 Secret Network 宣布使用 Octopus Network 构建的 NEAR-IBC 连接 NEAR 生态。 3、Louis 受邀作为嘉宾,在 NEARCON2023 的多链网络主题沙龙中发言:我们依然处于区…...

基于Maven构建OSGI应用(Maven和OSGI结合)
基于Maven构建OSGI应用。 使用Maven来构建项目,包括项目的创建、子模块buldle的创建等。使用OSGI来实现动态模块化管理,实现模块的热插拔效果(即插即用)。 创建一个Maven项目:helloworld,并在该项目下创建…...

oracle分组排序后取第一条
在 Oracle 中,可以使用「ROW_NUMBER」函数对某个列进行分组并排序,然后通过「WHERE」语句取第一条记录。 假设有一张「USERS」表,其中包含「ID」、「NAME」、「AGE」和「COUNTRY」列,您可以使用以下 SQL 语句对「AGE」列进行分组…...

MAMBA介绍:一种新的可能超过Transformer的AI架构
有人说,“理解了人类的语言,就理解了世界”。一直以来,人工智能领域的学者和工程师们都试图让机器学习人类的语言和说话方式,但进展始终不大。因为人类的语言太复杂,太多样,而组成它背后的机制,…...

win系统一台电脑安装两个不同版本的mysql教程
文章目录 1.mysql下载zip包(地址)2.解压在你的电脑上(不要再C盘和带中文的路径)3.创建my.ini文件4.更改环境变量(方便使用, 可选)5.打包mysql服务6.初始化mysql的data7.启动刚刚打包的服务8.更改密码 1.mys…...

esp32-s3部署yolox_nano进行目标检测
ESP32-S3部署yolox_nano进行目标检测 一、生成模型部署项目01 环境02 配置TVM包03 模型量化3.1预处理3.2 量化 04 生成项目 二、烧录程序 手上的是ESP32-S3-WROOM-1 N8R8芯片,整个链路跑通了,但是识别速度太慢了,20秒一张图,所以暂…...

TCP传输数据的确认机制
实际的TCP收发数据的过程是双向的。 TCP采用这样的方式确认对方是否收到了数据,在得到对方确认之前,发送过的包都会保存在发送缓冲区中。如果对方没有返回某些包对应的ACK号,那么就重新发送这些包。 这一机制非常强大。通过这一机制…...

使用Ansible Expect模块实现自动化交互式任务
Ansible是一种功能强大的自动化工具,可用于自动化配置管理、部署和任务执行。其中的Expect模块是Ansible的一个重要组件,它允许我们自动化处理需要与交互式命令行进行交互的任务。本文将介绍如何使用Ansible的Expect模块,并提供一些示例来说明…...

51单片机独立按键以及矩阵按键的使用以及其原理--独立按键 K1 控制 D1 指示灯亮灭以及数码管显示矩阵按键 S1-S16 按下后键值 0-F
IO 的使用–按键 本文主要涉及8051单片机按键的使用,包括独立按键以及矩阵按键的使用以及其原理,其中代码实例包括: 1.独立按键 K1 控制 D1 指示灯亮灭 2.通过数码管显示矩阵按键 S1-S16 按下后键值 0-F 文章目录 IO 的使用--按键一、按键消抖二、独立按…...

chrome安装jsonview
写在前面 通过jsonview可以实现,当http响应时application/json时直接在浏览器格式化显示,增加可读性。本文看下如何安装该插件到chrome中。 1:安装 首先在这里 下载插件包,然后解压备用。接着在chrome按照如下步骤操作…...

使用TouchSocket适配一个c++的自定义协议
这里写目录标题 说明一、新建项目二、创建适配器三、创建服务器和客户端3.1 服务器3.2 客户端3.3 客户端发送3.4 客户端接收3.5 服务器接收与发送 四、关于同步Send 说明 今天有小伙伴咨询我,他和同事(c端)协商了一个协议,如果使…...

VSC改造MD编辑器及图床方案分享
VSC改造MD编辑器及图床方案分享 用了那么多md编辑器,到头来还是觉得VSC最好用。这次就来分享一下我的blog文件编辑流吧。 这篇文章包括:VSC下md功能扩展插件推荐、图床方案、blog文章管理方案 VSC插件 Markdown All in One Markdown Image - 粘粘图片…...

SpringBoot的依赖管理和自动配置
与其明天开始,不如现在行动! 文章目录 1 依赖管理机制2 自动配置机制2.1 初步理解2.2 完整流程 💎总结 1 依赖管理机制 为什么导入starter-web后所有相关依赖都会导入进来? 开发什么场景,导入什么场景启动器-spring-bo…...

linux 定时任务
使用 crontab Usage: crontab [-u user] [-e|-l|-r] Crontab 的格式说明如下: * 逗号(‘,’) 指定列表值。如: “1,3,4,7,8″ * 中横线(‘-’) 指定范围值 如 “1-6″, 代表 “1,2,3,4,5,6″ * 星号 (‘*’) 代表所有可能的值 */15 表示每 15 分钟执行一次 # Use the ha…...

增强现实中的真实人/机/环与虚拟人/机/环
在增强现实中,真实人与虚拟人、真实机器与虚拟机器、真实环境与虚拟环境之间有着密切的关系。增强现实技术通过将真实与虚拟相结合,打破了传统的现实世界与虚拟世界的界限,创造出了一种新的体验方式。真实人、真实机器和真实环境与其对应的虚…...

Python网络爬虫环境的安装指南
网络爬虫是一种自动化的网页数据抓取技术,广泛用于数据挖掘、信息搜集和互联网研究等领域。Python作为一种强大的编程语言,拥有丰富的库支持网络爬虫的开发。本文将为你详细介绍如何在你的计算机上安装Python网络爬虫环境。 一、安装python开发环境 进…...

【MyBatis系列】MyBatis字符串问题
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

【Java】构建表达式二叉树和表达式二叉树求值
问题背景 1. 实现一个简单的计算器。通过键盘输入一个包含圆括号、加减乘除等符号组成的算术表达式字符串,输出该算术表达式的值。要求: (1)系统至少能实现加、减、乘、除等运算; (2)利用二叉…...

采用Python 将PDF文件按照页码进行切分并保存
工作中经常会遇到 需要将一个大的PDF文件 进行切分,比如仅需要大PDF文件的某几页 或者连续几页,一开始都是用会员版本的WPS,但是对于程序员,就是要采用技术白嫖 这里就介绍一个 python的PDF 包 PyPDF2 其安装方式也很简单 p…...

H264视频编码原理
说到视频,我们首先想到的可能就是占内存。我们知道一个视频是由一连串图像序列组成的,视频中图像一般是 YUV 格式。假设有一个电影视频,分辨率是 1080P,帧率是 25fps,并且时长是 2 小时,如果不做视频压缩的…...

UDP实现群聊
代码: import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.net.*; import java.io.IOException; import java.lang.String;public class liaotian extends JFrame{private static final int DEFAULT_PORT8899;private JLabel stateLB…...

服务器部署网易开源TTS | EmotiVoice部署教程
一、环境 ubuntu 20.04 python 3.8 cuda 11.8二、部署 1、docker方式部署 1.1、安装docker 如何安装docker,可以参考这篇文章 1.2、拉取镜像 docker run -dp 127.0.0.1:8501:8501 syq163/emoti-voice:latest2、完整安装 安装python依赖 conda create -n Emo…...

贪心算法和动态规划
目录 一、简介 二、贪心算法案例:活动选择问题 1.原理介绍 三、动态规划案例:背包问题 1.原理介绍 四、贪心算法与动态规划的区别 五、总结 作者其他文章链接 正则表达式-CSDN博客 深入理解HashMap:Java中的键值对存储利器-CSDN博客…...

jsp 设备预约管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目
一、源码特点 JSP 设备预约管理系统是一套完善的java web信息管理系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql5.0…...

Python:核心知识点整理大全10-笔记
目录 5.4 使用 if 语句处理列表 5.4.1 检查特殊元素 toppings.py 5.4.2 确定列表不是空的 5.4.3 使用多个列表 5.5 设置 if 语句的格式 5.6 小结 第6章 字 典 6.1 一个简单的字典 alien.py 6.2 使用字典 6.2.1 访问字典中的值 6.2.2 添加键—值对 6.2.3 先创建一…...

Hive数据库系列--Hive数据类型/Hive字段类型/Hive类型转换
文章目录 一、Hive数据类型1.1、数值类型1.2、字符类型1.3、日期时间类型1.4、其他类型1.5、集合数据类型1.5.1、Struct举例1.5.2、Array举例1.5.3、Map举例 二、数据类型转换2.1、隐式转换2.2、显示转换 三、字段类型的使用3.1、DECIMAL(precision,scale) 本章主要…...

在Spring Cloud中使用组件Ribbon和Feign,并分别创建子模块注册到Eureka中去
ok,在上篇文章中我们讲了在Spring cloud中使用Zuul网关,这篇文章我们将Spring Cloud的五大核心组件的Ribbon和Feign分别创建一个微服务模块。 题外话,本篇博客就是配置子模块,或者说是微服务,然后将微服务正式启动之前…...

(JAVA)-缓冲流
缓冲流能高效的读取数据 缓冲流底层自带了8192的缓冲区提高性能,他在原有的流上进行了包装,加上了缓冲效果 原理: 读入时首先会将内存中缓冲区大小的数据读入缓冲区中,接着下次读取直接从缓冲区中读取数据,当缓冲区…...