它用于虚拟DOM,组件化设计模式,声明式代码,单向数据流,使用jsx描述信息等特点
复用的代码可以抽成组件共同使用(UI,方法等)
数据主要从父节点传到子节点(通过props),如果父级的某个props改变了,React会重新渲染所有子节点
若子组件想要改版父子组件的值应该如果去做呢?
如下:event事件,子组件是不能够在自己的组件中去修改父组件的值,所以子组件中可以通过调用父组件的方法在父组件的方法中修改父组件的值
// 父组件
import React, {Component} from 'react'
import Child from './Child'
class Parent extends Component{ // 初始化constructor(props){super(props)this.state = {message: '我是从父组件传过来的'}} handleUpdate = () =>{this.setState({message: '子组件修改父组件的值'})}// 渲染render(){return(this.state.message} event={this.handleUpdate()}/> )}
}
export default Parent// 子组件
import React, {Component} from 'react'
class Child extends Component{ // 初始化constructor(props){super(props)} // 渲染render(){return({this.props.message})}
}
export default Child
优点:
缺点:
相似之处:
不同点 :
主要用于列表中元素被修改,删除或添加的标识。在diff算法中,key用来判断该元素节点是被删除还是创建减少不必要的元素重复渲染。
作用:用来计算VirtualDOM中被改变部分,针对该部分进行原生DOM操作,不用重新渲染整个页面
举例子:如果两个组件都需要用到对方的状态,那么这时候就可以用到状态提升。具体做法是把两个子组件的状态写到他们的父组件中,然后父组件把状态传递给子组件的props中去,这样子组件也相当于有状态。
父组件
import React from "react"
import Child1 from "./child1"
import Child2 from "./child2"export default class Parent extends React.Component {constructor() {super()this.state = {money: 1}}changeHander(e){this.setState({money: e.target.value})}render() {return ( this.state.money } onChange={this.changeHander.bind(this)} />Parent
人民比: this.state.money} />美金: this.state.money} /> )}
}
子组件1
import React from "react"export default class Child1 extends React.Component{constructor(){super()this.state = {input1: 0}}componentDidMount(){this.setState({input1: this.props.money})}changeHander(e) {this.setState({input1: e.target.value})}render() {return({ this.props.money } this.state.input1 } onChange={ this.changeHander.bind(this) }/>)}
}
子组件2
import React from "react"export default class Child2 extends React.Component{constructor(){super();this.state = {input2: 1}}componentDidMount(){this.setState({input2: this.props.money * 7})}changeHander(e) {this.setState({input2: e.target.value})}render() {return({ this.props.money * 7} this.state.input2 } onChange={ this.changeHander.bind(this) }/>)}
}
setState会进行状态更新
将传入的参数对象与组件当前状态合并,然后触发所谓的调和过程,经过调和过程,根据新的state,React元素会重新构建虚拟DOM,进行diff算法对比新旧虚拟DOM树的区别,进行视图更新,而不是全部渲染
setState 采用的任务队列机制,不会马上执行,而是加入队列,在下次事件循环是一次性执行
this.props和this.state的更新可能是异步的,不能依赖他们的值去计算下一个state
// bind
// 1
该函数会在setState函数调用完成并且组件开始重渲染的时候被调用,我们可以用该函数来监听渲染是否完成
在super() 被调用之前,子类是不能使用 this 的,在 ES5 中,子类必须在 constructor 中调用 super()。传递 props 给 super() 的原因则是便于(在子类中)能在 constructor 访问 this.props
| Real DOM | Virtual DOM |
|---|---|
| 1.更新缓慢 | 1.更新更快 |
| 2.可以直接更新HTML | 2.无法直接更新HTML |
| 3.如果元素更新,则创建新DOM | 3.如果元素更新,则更新JSX |
| 4.DOM操作代价很高 | 4.DOM操作很简单 |
| 5.消耗的内存较多 | 5.很少消耗内存 |
只读组件,必须保持纯函数,即不可变。它们总是再整个应用中从父组件传递到子组件。子组件永远不能将prop送回到父组件。这有助于维护单向数据流,通常用于呈现动态生成的数据
是React 组件的核心,是数据的来源,必须尽可能简单。基本上状态是确定组件呈现和行为的对象。与props不同,它们是可变的,并创建动态和交互式组件。可以通过this.state()访问它们。
| 条件 | State | Props |
|---|---|---|
| 1.从父组件中接收初始值 | Y | Y |
| 2.父组件可以改变值 | N | Y |
| 3.在组件中设置默认值 | Y | Y |
| 4.在组件的内部变化 | Y | N |
| 5.设置子组件的初始值 | Y | Y |
| 6.在子组件的内部更改 | N | Y |
this.setState()更新组件的状态。class MyComponent extends React.Component {constructor() {super();this.state = {name: 'Maxx',id: '101'}}render(){setTimeout(()=>{this.setState({name:'Jaeha', id:'222'})},2000)return ( Hello {this.state.name}
Your Id is {this.state.id}
);}}
ReactDOM.render( , document.getElementById('content')
);class App extends React.Component{constructor(props);this.state={count:1title:'数字计算'}
}handleClick=()=>{this.replaceState({count:this.state.count+1})
}render(){return(this.onClick}>点我 )}
}count:1
| 有状态组件 | 无状态组件 |
|---|---|
| 1.在内存中存储有关组件状态变化的信息 | 1.计算组件的内部状态 |
| 2.有权改变状态 | 2. 无权改变状态 |
| 3.包含过去、现在和未来可能的状态变化情况 | 3. 不包含过去,现在和未来可能发生的状态变化情况 |
| 4.接受无状态组件状态变化要求的通知,然后将 props 发送给他们。 | 4.从有状态组件接收 props 并将其视为回调函数。 |
难度:⭐️
虚拟DOM(VDOM)它是真实DOM的内存表示,一种编程概念,一种模式。它会和真实的DOM同步,比如通过ReactDOM这种库,这个同步的过程叫做调和(reconcilation)。
虚拟DOM更多是一种模式,不是一种特定的技术。
难度:⭐️⭐️
类组件( Class components )
无论是使用函数或是类来声明一个组件,它决不能修改它自己的 props 。
props 。React是单项数据流,父组件改变了属性,那么子组件视图会更新。
props 是外界传递过来的,状态 state 是组件本身的,状态可以在组件中任意修改class Welcome extends React.Component {render() {return (Welcome { this.props.name }
);}
}
ReactDOM.render( , document.getElementById('root'));
函数组件(functional component)
props 对象并返回了一个React元素function **Welcome** (props) { return Welcome {props.name}
} ReactDOM.render( , document.getElementById('root'));
区别
函数组件和类组件当然是有区别的,而且函数组件的性能比类组件的性能要高,因为类组件使用的时候要实例化,而函数组件直接执行函数取返回结果即可。为了提高性能,尽量使用函数组件。
区别 函数组件类组件是否有this没有有是否有生命周期没有有是否有状态state没有有
难度:⭐️⭐️
Refs 是使用 React.createRef() 方法创建的,并通过 ref 属性添加到 React 元素上。为了在整个组件中使用 refs ,只需将 ref 分配给构造函数中的实例属性
class MyComponent extends React.Component {constructor(props) {super(props);this.myRef = React.createRef();}render() {return ;}
}
和:
class UserForm extends Component {handleSubmit = () => {console.log("Input Value is: ", this.input.value)}render () {return ()}
}
我们还可以借助闭包在功能组件中使用它。
难度:⭐️⭐️
Refs 是 React 提供给我们的安全访问 DOM 元素或者某个组件实例的句柄。
我们可以为元素添加 ref 属性然后在回调函数中接受该元素在 DOM 树中的句柄,该值会作为回调函数的第一个参数返回:
class UnControlledForm extends Component {handleSubmit = () => {console.log("Input Value: ", this.input.value)}render () {return ()}
}
上述代码中的 input 域包含了一个 ref 属性,该属性声明的回调函数会接收 input 对应的 DOM 元素,我们将其绑定到 this 指针以便在其他的类函数中使用。
另外值得一提的是,refs 并不是类组件的专属,函数式组件同样能够利用闭包暂存其值:
function CustomForm ({handleSubmit}) {let inputElementreturn ()
}
难度:⭐️⭐️
为了解决跨浏览器兼容性问题,React中的事件处理程序将传递SyntheticEvent实例,该实例是React跨浏览器本机事件的跨浏览器包装器。这些综合事件具有与您惯用的本机事件相同的界面,除了它们在所有浏览器中的工作方式相同。
有点有趣的是,React实际上并未将事件附加到子节点本身。React将使用单个事件侦听器在顶层侦听所有事件。这对性能有好处,也意味着React在更新DOM时无需担心跟踪事件监听器。
难度:⭐️⭐️
state 和 props都是普通的JavaScript对象。尽管它们两者都具有影响渲染输出的信息,但它们在组件方面的功能不同。即
props 是一个从外部传进组件的参数,主要作为就是从父组件向子组件传递数据,它具有可读性和不变性,只能通过外部组件主动传入新的 props 来重新渲染子组件,否则子组件的 props 以及展现形式不会改变。state 的主要作用是用于组件保存、控制以及修改自己的状态,它只能在 constructor 中初始化,它算是组件的私有属性,不可通过外部访问和修改,只能通过组件内部的 this.setState 来修改,修改 state 属性会导致组件的重新渲染。难度:⭐️⭐️
高阶组件就是一个函数,且该函数接受一个组件作为参数,并返回一个新的组件。基本上,这是从React的组成性质派生的一种模式,我们称它们为 “纯”组件, 因为它们可以接受任何动态提供的子组件,但它们不会修改或复制其输入组件的任何行为。
const EnhancedComponent = higherOrderComponent(WrappedComponent);
高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧
高阶组件的参数为一个组件返回一个新的组件
组件是将 props 转换为 UI,而高阶组件是将组件转换为另一个组件
在调用方法之前,子类构造函数无法使用 this 引用 super() 。
在ES6中,在子类的 constructor 中必须先调用 super 才能引用 this 。
在 constructor 中可以使用 this.props
class MyComponent extends React.Component {constructor(props) {super(props);console.log(this.props); // Prints { name: 'sudheer',age: 30 }}
}
class MyComponent extends React.Component {constructor(props) {super();console.log(this.props); // Prints undefined// But Props parameter is still availableconsole.log(props); // Prints { name: 'sudheer',age: 30 }}render() {// No difference outside constructorconsole.log(this.props) // Prints { name: 'sudheer',age: 30 }}
}
上面的代码片段揭示了this.props行为仅在构造函数中有所不同。外部构造函数相同。
难度:⭐️⭐️⭐️
在HTML当中,像 , , 和 `` 这类表单元素会维持自身状态,并根据用户输入进行更新。但在React中,可变的状态通常保存在组件的状态属性中,并且只能用 setState() 方法进行更新。
非受控组件,即组件的状态不受React控制的组件,例如下边这个
import React, { Component } from 'react';
import ReactDOM from 'react-dom';class Demo1 extends Component {render() {return ()}
}ReactDOM.render( , document.getElementById('content'))
在这个最简单的输入框组件里,我们并没有干涉input中的value展示,即用户输入的内容都会展示在上面。如果我们通过props给组件设置一个初始默认值,defaultValue属性是React内部实现的一个属性,目的类似于input的placeholder属性。
同样的,受控组件就是组件的状态受React控制。上面提到过,既然通过设置input的value属性, 无法改变输入框值,那么我们把它和state结合在一起,再绑定onChange事件,实时更新value值就行了。
class Demo1 extends Component {constructor(props) {super(props);this.state = {value: props.value}}handleChange(e) {this.setState({value: e.target.value})}render() {return ( this.handleChange(e)}/>)}
}
难度:⭐️⭐️⭐️
const element = (Hello, world!
);
以下等同于什么使用 React.createElement ?
const element = React.createElement('h1',{className: 'greeting'},'Hello, world!'
);
难度:⭐️⭐️⭐️
JSX即JavaScript XML。一种在React组件内部构建标签的类XML语法。JSX为react.js开发的一套语法糖,也是react.js的使用基础。React在不使用JSX的情况下一样可以工作,然而使用JSX可以提高组件的可读性,因此推荐使用JSX。
class MyComponent extends React.Component {render() {let props = this.props; return ();}
}
优点:
1.允许使用熟悉的语法来定义 HTML 元素树;
2.提供更加语义化且移动的标签;
3.程序结构更容易被直观化;
4.抽象了 React Element 的创建过程;
5.可以随时掌控 HTML 标签以及生成这些标签的代码;
6.是原生的 JavaScript。
难度:⭐️⭐️⭐️
如果进行如下方式更新状态,那么它将不会重新渲染组件。
//WrongThis.state.message =”Hello world”;
而是使用 setState() 方法。它计划对组件状态对象的更新。状态改变时,组件通过重新渲染做出响应
//CorrectThis.setState({message: ‘Hello World’});
注意:可以分配状态的唯一位置是构造函数。
难度:⭐️⭐️⭐️
React组件的生命周期分为四个不同阶段:

难度:⭐️⭐️⭐️
setTimeout 或 setInterval )进行集成,在这里使用它来更新状态,以便我们可以触发其他生命周期方法。props 就被调用。 当我们更新状态时,从 setNewNumber 触发它。详细参见 git 千峰React全家桶.pdf
老生命周期的问题
1. componentWillMount,在ssr中,这个方法将会被多次调用,所以会重复出发多遍,同时在这里如果绑定事件,将无法解绑,导致内存泄漏,变得不够安全高效而逐步废弃.
2. componentWillReceiveProps 外部组件多次频繁更新传入多次不同的props,会导致不必要的异步请求.
3. componentWillUpdate ,更新前记录DOM的状态,可能会做一些处理,与componentDidUpdate如果间隔时间太长,会导致状态不可信
新生命周期的替代
getDerivedStateFromProps 第一次的初始化组件以及后续的更新过程中(包括资深状态更新以及父传子),返回一个对象作为新的state,返回null则说明不需要在这里更新state
getSnapShotBeforeUpdate 取代了componentWillUpdate 触发时间为update发生的时候,在render之后dom渲染之前返回一个值,作为componentDidUpdate的第三个参数.
难度:⭐️⭐️⭐️
…在此React(使用JSX)代码中做什么?它叫什么?
扩展传值符号。它是在ES2018中添加的(数组/可迭代对象的传播较早,ES2015)。
例如,如果this.props包含a:1和b:2,则
与以下内容相同:
扩展符号不仅适用于该用例,而且对于创建具有现有对象的大多数(或全部)属性的新对象非常方便-在更新状态时会遇到很多问题,因为您无法修改状态直:
this.setState(prevState => {return {foo: {...prevState.foo, a: "updated"}};
});
难度:⭐️⭐️⭐️
hooks 是react 16.8 引入的特性,他允许你在不写class的情况下操作state 和react的其他特性。
hooks 只是多了一种写组件的方法,使编写一个组件更简单更方便,同时可以自定义hook把公共的逻辑提取出来,让逻辑在多个组件之间共享。
Hook 是什么? Hook 是一个特殊的函数,它可以让你“钩入” React 的特性。例如,useState 是允许你在 React 函数组件中添加 state 的 Hook。稍后我们将学习其他 Hook。
什么时候我会用 Hook? 如果你在编写函数组件并意识到需要向其添加一些 state,以前的做法是必须将其它转化为 class。现在你可以在现有的函数组件中使用 Hook。
难度:⭐️⭐️⭐️
案例:
import { useState } from 'react';function Example() {const [count, setCount] = useState(0);return (You clicked {count} times
setCount(count + 1)}>Click me )
}
function useState(initialState: S | (() => S)): [S, Dispatch>];
其中 state 是他的值, setState 是用来设置值的函数, initialState 是初始值
该初始值可以接受任何参数,但是记得当他接受为一个函数时,就变成了 Lazy initialization (延迟初始化)
该函数返回值即为initialState
const [count, setCount] = useState(0);const [count, setCount] = useState(()=>0);
// 这两种初始化方式 是相等的,但是在函数为初始值时会被执行一次const [count, setCount] = useState(()=>{console.log('这里只会在初始化的时候执行')// class 中的 constructor 的操作都可以移植到这里return 0
});
// 当第一次执行完毕后 就和另一句的代码是相同的效果了
也许很多人 在使用 class 的 setState 时候,会经常使用他的回调函数,
但是这里很遗憾,他只接受新的值,如果想要对应的回调,可以使用useEffect,这个问题等会会提供一个跳转链接
难度:⭐️⭐️⭐️
React的StrictMode是一种帮助程序组件,可以帮助您编写更好的react组件,您可以使用包装一些组件, `` 并且基本上可以:
难度:⭐️⭐️⭐️
在JavaScript中, this 的值取决于当前上下文。在React类的组件方法中,开发人员通常希望它引用组件的当前实例,因此有必要 将 这些方法 绑定 到该实例。通常,这是在构造函数中完成的,例如:
class SubmitButton extends React.Component {constructor(props) {super(props);this.state = {isFormSubmitted: false};this.handleSubmit = this.handleSubmit.bind(this);}handleSubmit() {this.setState({isFormSubmitted: true});}render() {return (Submit )}
}
难度:⭐️⭐️⭐️⭐️
React文档官网并未对 Context 给出“是什么”的定义,更多是描述使用的 Context 的场景,以及如何使用 Context 。
官网对于使用 Context 的场景是这样描述的:
In Some Cases, you want to pass data through the component tree without having to pass the props down manuallys at every level. you can do this directly in React with the powerful “context” API.
简单说就是,当你不想在组件树中通过逐层传递 props 或者 state 的方式来传递数据时,可以使用 Context 来实现 跨层级 的组件数据传递。

使用props或者state传递数据,数据自顶下流。

使用 Context ,可以跨越组件进行数据传递。
难度:⭐️⭐️⭐️⭐️
React Fiber 并不是所谓的纤程(微线程、协程),而是一种基于浏览器的单线程调度算法,背后的支持 API 是大名鼎鼎的:requestIdleCallback。
Fiberl是一种将 recocilation (递归 diff),拆分成无数个小任务的算法;它随时能够停止,恢复。停止恢复的时机取决于当前的一帧(16ms)内,还有没有足够的时间允许计算。