React
react官网:https://reactjs.org/
1. 认识React
react:用于构建用户界面的JavaScript库
由Facebook开发,且开源
react特点:
-
采用组件化模式,声明式编码,提高开发效率及组件复用率
-
在React Nativev中可以使用React语法进行移动端开发
-
使用虚拟DOM + 优秀的Diffing算法,尽量减少与真实DOM的交互
开发React必须依赖三个库
-
react:包含react所必须的核心代码
-
react-dom:react渲染在不同平台所需要的核心代码
-
react-dom包含react web 和 react-native
-
react-web:react-dom会将jsx最终渲染成真实的DOM,显示在浏览器中
-
react-native:react-dom会将jsx最终渲染成原生的控件
- babel:将jsx转换为React代码的工具
React依赖引入
<!-- react -->
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<!-- react-dom -->
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<!-- babel -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
注意:这里引入的版本是 react 18
使用
必须在script标签上加上type属性 type=“text/babel”
因为我们在react中写的是jsx语法,需要babel转换
// React18
const root = ReactDOM.createRoot(document.querySelector("#root"))
// 使用reder函数进行渲染
// 注意里面没有双引号,直接写标签,写双引号就当作字符串来解析
root.render(<h1>hello world</h1>)
React组件化
React组件化分为类组件和函数组件
类组件
就是一个class类
用法:
-
用class创建一个类
-
继承React.Component
-
将这个组件通过render函数渲染到页面上
继承了React.Component,这个类就是一个组件
2.React 中 JSX语法
-
JSX 是 JavaScript XML 的简写,表示 JavaScript 代码中写 XML(HTML)格式的代码
-
优势:声明式语法更加直观、与 HTML 结构相同,降低了学习成本、提升开发效率
-
JSX 是 react 的核心内容
:::
JSX 是React 的核心内容
JSX 表示在JS代码中写HTML结构,是React声明式的体现
使用 JSX 配合嵌入的 JS 表达式、条件渲染、列表渲染,可以描述任意 UI 结构
推荐使用 className 的方式给JSX添加样式
:::
为什么React选择JSX
因为html和js逻辑密不可分,所以React没有将它们分离到不同的文件中,而是将它们组合到了一起,这个地方就是组件
注释内容
:::
{ /* 注释内容 */ }
:::
JSX内容
jsx插入子元素不同类型处理
- 当变量是Number、String、Array 时,会直接显示
constructor() {
super()
this.state = {
arr:["a", "b", "c", "d", "e"],
}
}
render() {
return (
<div>
<h1>hello {this.state.arr}</h1>
</div>
)
}
-
当变量时null、undefined、Boolean类型时,显示的内容为空
constructor() { super() this.state = { undfEl: undefined, } } render() { return ( <div> <h2>{this.state.undfEl}</h2> ) }
-
当变量是Object对象类型,会报错
constructor() {
super()
this.state = {
obj: {
name: "小罗"
}
}
}
render() {
return (
<div>
{/* 直接使用会报错 */}
<h2>{this.state.obj}</h2>
{/* 可以通过Object方法来获取里面的值 */}
<h2>{Object.values(this.state.obj)}</h2>
<h2>{Object.entries(this.state.obj)}</h2>
</div>
)
}
# 3.JSX属性和class、style绑定
### JSX属性绑定
constructor() {
super()
this.state = {
names: "hello world",
hrefUrla: 'http://www.baidu.com'
}
}
render() {
const { names , hrefUrla} = this.state
return (
<div>
<h3 title={ names }>{names}</h3>
<a href={hrefUrla}>百度</a>
</div>
)
}
JSXclass绑定
方式一:直接写
<h1 className="abc dbc"></h1>
方式二:字符串拼接
constructor() {
super()
this.state = {
isActive: true
}
}
render() {
const {isActive } = this.state
const classNames = `abc cba ${isActive ? 'active' : " "}`
return (
<div>
<h1 className="abc dbc"></h1>
<h2 className={classNames}></h2>
</div>
)
}
方式三:数组
constructor() {
super()
this.state = {
isActive: true
}
}
render() {
const { isActive } = this.state
const classLists = ['abc','dbc']
if(isActive) {
classLists.push("active")
}
return (
<div>
<h2 className={classLists.join(" ")}></h2>
</div>
)
}
JSXstyle绑定
- 对象写法
class App extends React.Component { constructor() { super() this.state = { } } render() { const styleBgc = { color:'red', backgroundColor:'skyblue' } return ( <div> <h2 style={{color:'red',backgroundColor:'skyblue'}}>hello world</h2> {/* 等同于下面这个 */} <h2 style={styleBgc}>hello world</h2> </div> ) } ```
4.事件绑定-this的三种绑定方式
constructor() {
super()
this.state = {
}
}
render() {
return (
<div>
<h2></h2>
{/* bind */}
<button onClick={this.btns.bind(this)}>按钮1</button>
{/* 事件为箭头函数 */}
<button onClick={this.btns2}>按钮2</button>
{/* 直接传入一个箭头函数,箭头函数返回事件 */}
<button onClick={() => this.btns3()}>按钮3</button>
</div>
)
}
btns() {
console.log(this)
}
btns2 = () => {
console.log(this)
}
btns3() {
console.log(this)
}
5.React组件化开发
react的组件相对于Vue更加的灵活和多样,按照不同的方式可以分为很多类组件
-
根据组件的定义方式,可以分为:函数组件(Fuctional Component) 和类组件(Class Component)
-
根据组件内部是否有状态需要维护,可以分为:无状态组件(Srareless Component)和有状态组件(Stateful Component)
-
根据组件的不同职责,可以分为:展开型组件(Presentational Component) 和容器型组件(Container Component)
-
函数组件、无状态组件、展示型组件主要关注UI的展示
-
类组件、有状态组件、容器型组件主要关注数据逻辑
类组件
类组件定义要求:
-
组件的名称要大写字符开头(函数组件也是)
-
类组件要继承React.Component
-
类组件必须要实现render函数
定义一个类组件:
-
constructor是可选的,通常在constructor中初始化一些数据
-
this.state中维护的就是组件内部的数据
-
render()方法是class组件中唯一必须实现的方法
render函数的返回值
-
React元素
-
数组或fragments
-
Portals
-
字符串或数值类型
-
布尔类型或null
函数组件
函数组件是使用function来进行定义的函数,函数组件返回和类组件中render返回一样的内容
function App() {
return (
<div>
<h1>你好小罗</h1>
</div>
)
}
export default App
函数组件的特点(除hooks外):
-
没有生命周期,也会被更新并挂载,但是没有生命周期函数
-
this关键字不能指向组件实例(因为没有组件实例)
-
没有内部状态(state)
6.React组件生命周期
React生命周期指的是类组件生命周期,因为函数组件没有生命周期
生命周期:
是一个抽象概念,在生命周期整个过程中,分成了很多个阶段,每个组件都有属于它的生命周期,从一个组件创建、数据初始化、挂载、更新、销毁,这个就是一个组件所谓的生命周期
生命周期钩子:生命周期事件,生命周期函数,会对组件内部实现某些函数进行回调
1.componentDidMount()
代表DOM挂载成功
-
首先执行构造方法constructor()
-
再次执行render函数
-
当上面两个执行完成后执行componentDidMount生命周期钩子
2. componentDidUpdate()
代表组件更新回调的函数
-
当组件数据被修改时,首先会重新执行render()函数
-
然后再执行componentDidUpdate()生命周期钩子
3.componentWillUnmount()
代表组件被销毁回调的函数
7.不常用的生命周期
1.shouldComponentUpdate()
进行判断是否进行更新渲染render()函数,返回flase不更新,返回true正常更新
2.getSnapshotBeforeUpdate
在React更新DOM之前回调的一个函数,也就是render函数执行完了
8.React组件通信
父传子
父组件通过 属性=值 的形式来传递给子组件数据
子组件通过 props 参数获取父组件传递过来的数据
PropTypes类型检查
https://zh-hans.reactjs.org/docs/typechecking-with-proptypes.html
-
子组件引入 propTypes
import propTypes from “prop-types”
-
再通过类.propTypes = {} 进行限制
默认值:defaultProps
子传父
和父传子是一样的,只不过传递的是属性 是一个函数,其实就是在父组件中修改,只不过需要子组件调用执行
-
父组件定义函数
-
子组件通过 this.props调用 父组件传递的函数
9.React插槽使用
首先React中没有插槽概念
插槽概念:允许开发者在封装组件时,把不确定的、希望由用户指定的部分定义为插槽。
实现插槽
React实现插槽非常灵活,有两种方案实现:
-
组件的children子元素
-
props属性传递React元素
组件的children实现插槽
步骤:
-
在组件里面写好元素,会传入到组件的this.props.children里面
-
当组件里面有多个元素 children是一个数组
-
当组件里面只有一个元素 children是一个元素
10.React非父子通信
11.setState的使用
setState来告知React数据已经发生变化
setState方法是从Component中继承过来的
setState传入对象
传入的对象会和 this.state 对象合并,本质使用了 Object.assign()
setState传入函数
函数写法可以获取到上一次的state 和父组件传递过来的props
函数里面返回的也是一个对象
SetState是异步更新
先打印 哈哈哈 再修改 message
setState第二个参数
setState 是一个回调函数,可以用于获取更新好的state的数据
12.React性能优化SCU
当我们修改this.setState的数据时,render函数就会重新执行,我们可以通过shouldComponentUpdate生命周期来判断是否重新渲染,返回false 就是不渲染,但是每次都手动添加比较麻烦,所以我们可以使用PureComponent
PureComponent
就是将类 class 继承 PureComponent 即可
memo
函数组件中使用 memo 来进行控制是否渲染
使用:
-
导入 memo
-
将函数用 memo包裹
import { memo } from “react”
const Foo = memo(function () {
console.log(“Foo render”)
return (
Foo
)
})
export default Foo
13.获取DOM方式refs
createRef()
ref可以获取组件实例,可以调用其他组件里面的方法,只能对类组件有用,函数组件没有实例,可以通过forwardRef()来获取函数式组件里面的DOM
forwardRef()
使用:
-
函数式组件里面导入 forwardRef() 对函数进行一个包裹,
-
在 通过 ref 进行绑定
14.受控和非受控组件
15.React的高阶组件
16.portals和fragment
17.StirctMode严格模式