react中的事件都是合成事件,不是把每一个dom的事件绑定在dom上,而是把事件统一绑定到document中,触发时通过事件冒泡到document进行触发合成事件,因为是合成事件,所以我们无法去使用e.stopPropagation去阻止,而是使用
e.preventDefault
去阻止。
组件装载/更新 -> 新增/删除事件 -> eventplugin添加到ListennerBank中监听事件 -> 触发事件 -> 生成合成事件 -> 通过唯一key获取到指定函数 -> 执行指定回调函数 -> 执行完毕后释放
- React 是 Facebook 在 2011 年开发的前端 JavaScript 库。
- 它遵循基于组件的方法,有助于构建可重用的UI组件。
- 它用于开发复杂和交互式的 Web 和移动 UI。
- 尽管它仅在 2015 年开源,但有一个很大的支持社区。
- 使用虚拟DOM而不是真正的DOM。
- 可以用服务器端渲染。
- 遵循单向数据流或数据绑定。
组件定义要求:1. 组件名称必须以大写字母开头;2. 组件的返回值只能有一个根元素
函数组件的性能比类组件的性能要高,因为类组件使用的时候要实例化,而函数组件直接执行函数取返回结果即可。为了提高性能,尽量使用函数组件
区别 | 函数组件 | 类组件 |
---|---|---|
是否有 this |
没有 | 有 |
是否有生命周期 | 没有 | 有 |
是否有状态 state |
没有 | 有 |
注意
props
。props
。props
是外界传递过来的,状态 state
是组件本身的,状态可以在组件中任意修改
- 它提高了应用的性能
- 可以方便地在客户端和服务器端使用
- 由于 JSX,代码的可读性很好
- React 很容易与 Meteor,Angular 等其他框架集成
- 使用React,编写UI测试用例变得非常容易
函数组件比起类组件“少”了很多东西,比如生命周期、对 state 的管理等。这就给函数组件的使用带来了非常多的局限性。
作用:React-Hooks 的出现,就是为了帮助函数组件补齐这些(相对于类组件来说)缺失的能力
优点:
缺点:
- React 只是一个库,而不是一个完整的框架
- 它的库非常庞大,需要时间来理解
- 新手程序员可能很难理解
- 编码变得复杂,因为它使用内联模板和 JSX
JSX 是
JavaScript XML
的简写,是 React 使用的一种文件
利用 JavaScript 的表现力和类似 HTML 的模板语法,使得 HTML 文件非常容易理解。此文件能使应用非常可靠,并能够提高其性能
使得组件间的通信更容易追踪和管理
Refs
是React
提供给我们的安全访问DOM
元素或者某个组件实例的句柄- 可以为元素添加
ref
属性然后在回调函数中接受该元素在DOM
树中的句柄,该值会作为回调函数的第一个参数返回
React 生命周期分为三种状态 1. 初始化 2.更新 3.销毁
初始化阶段
getDefaultProps()
设置默认的props,也可以用dufaultProps设置组件的默认属性.
getInitialState()
在使用es6的class语法时是没有这个钩子函数的,可以直接在constructor中定义this.state。此时可以访问this.props
componentWillMount()
组件初始化时只调用,以后组件更新不调用,整个生命周期只调用一次,此时可以修改state。
在渲染前调用,在客户端也在服务端。
render()
react最重要的步骤,创建虚拟dom,进行diff算法,更新dom树都在此进行。此时就不能更改state了。
componentDidMount()
组件渲染之后调用,只调用一次。
在第一次渲染后调用,只在客户端。之后组件已经生成了对应的DOM结构,可以通过**thi.getDOMNode()**来进行访问。
- 可以在这个方法中调用****setTimeout, setInterval或者发送****AJAX请求等操作(防止异步操作阻塞UI)。
更新阶段
componentWillReceiveProps(nextProps)
组件初始化时不调用,组件接受新的props时调用。
使用componentWillReceiveProps的时候,不要去向上分发,调用父组件的相关setState方法,否则会成为死循环
- 在组件接收到一个新的 prop (更新后)时被调用。这个方法在初始化render时不会被调用。
shouldComponentUpdate(nextProps, nextState)
react性能优化非常重要的一环。组件接受新的state或者props时调用,返回一个布尔值
- 可以在你确认不需要更新组件时使用,节省大量性能,尤其是在dom结构复杂的时候
componentWillUpdata(nextProps, nextState)
组件初始化时不调用,只有在组件将要更新时才调用,此时可以修改state
render()
组件重新渲染
componentDidUpdate()
组件初始化时不调用,组件更新完成后调用,此时可以获取dom节点。
卸载阶段
组件将要卸载时调用,一些事件监听和定时器需要在此时清除。
只执行一次: constructor、componentWillMount、componentDidMount
执行多次:render 、子组件的componentWillReceiveProps、componentWillUpdate、componentDidUpdate
有条件的执行:componentWillUnmount(页面离开,组件销毁时)
不执行的:根组件(ReactDOM.render在DOM上的组件)的componentWillReceiveProps(因为压根没有父组件给传递props)
componentWillMount
组件挂载之前render
组件的渲染方法componentDidMount
组件挂载完成执行Updation中为组件数据发生变化的过程
componentWillReceiveProps
:props独有
子组件从父组件接受的props数据发生变动这时此方法才会被触发。
shouldComponentUpdata
:props和states共有
是否要更新数据?需要一个返回值true继续执行下面的生命周期,false就会终止当前组件数
componentWillUpdate
组件将要更新render
组件的重新渲染componentDidUpdata
组件完成更新Unmounting组件卸载
componentWillUnmount
组件销毁的时候触发Virtual DOM 是一个轻量级的 JavaScript 对象,它最初只是 real DOM 的副本
是一个节点树,将元素、属性和内容作为对象及其属性
工作过程
浏览器只能处理 JavaScript 对象,而不能读取常规 JavaScript 对象中的 JSX
为了使浏览器能够读取 JSX,需要用像 Babel 这样的 JSX 转换器将 JSX 文件转换为 JavaScript 对象,然后再将其传给浏览器。
React | Angular | |
---|---|---|
1. 体系结构 | 只有 MVC 中的 View | 完整的 MVC |
2. 渲染 | 可以在服务器端渲染 | 客户端渲染 |
3. DOM | 使用 virtual DOM | 使用 real DOM |
4. 数据绑定 | 单向数据绑定 | 双向数据绑定 |
5. 调试 | 编译时调试 | 运行时调试 |
6. 作者 |
组件是 React 应用 UI 的构建块。
这些组件将整个 UI 分成小的独立并可重用的部分。
每个组件彼此独立,而不会影响 UI 的其余部分。
// ES5
var React = require('react');
// ES6
import React from 'react';
// ES5
module.exports = Component;
// ES6
export default Component;
// ES5
var MyComponent = React.createClass({
render: function() {
return
<h3>Hello Edureka!</h3>;
}
});
// ES6
class MyComponent extends React.Component {
render() {
return
<h3>Hello Edureka!</h3>;
}
}
// ES5
var App = React.createClass({
propTypes: { name: React.PropTypes.string },
render: function() {
return
<h3>Hello, {this.props.name}!</h3>;
}
});
// ES6
class App extends React.Component {
render() {
return
<h3>Hello, {this.props.name}!</h3>;
}
}
// ES5
var App = React.createClass({
getInitialState: function() {
return { name: 'world' };
},
render: function() {
return
<h3>Hello, {this.state.name}!</h3>;
}
});
// ES6
class App extends React.Component {
constructor() {
super();
this.state = { name: 'world' };
}
render() {
return
<h3>Hello, {this.state.name}!</h3>;
}
}
每个React组件强制要求必须有一个 render()。它返回一个 React 元素,是原生 DOM 组件的表示。
render()
必须每次调用时都返回相同的结果
状态是 React 组件的核心,是组件内数据的来源,必须尽可能简单
状态是确定组件呈现和行为的对象。与props 不同,它们是可变的,并创建动态和交互式组件
可以通过this.state()
访问它们
Props 是 React 中属性的简写,Props是只读组件,不可变
它们总是在整个应用中从父组件传递到子组件。子组件永远不能将 prop 送回父组件。
这有助于维护单向数据流,通常用于呈现动态生成的数据。
函数组件和类组件
条件 | State | Props |
---|---|---|
1. 从父组件中接收初始值 | Yes | Yes |
2. 父组件可以改变值 | No | Yes |
3. 在组件中设置默认值 | Yes | Yes |
4. 在组件的内部变化 | Yes | No |
5. 设置子组件的初始值 | Yes | Yes |
6. 在子组件的内部更改 | Yes | No |
可以用
this.setState()
更新组件的状态。
箭头函数(()=>{})是用于编写函数表达式的简短语法
箭头函数允许正确绑定组件的上下文,因为在 ES6 中默认下不能使用自动绑定。
作用:使用高阶函数及类组件时,箭头函数非常有用。
有状态组件 | 无状态组件 |
---|---|
1. 在内存中存储有关组件状态变化的信息 | 1. 计算组件的内部的状态 |
2. 有权改变状态 | 2. 无权改变状态 |
3. 包含过去、现在和未来可能的状态变化情况 | 3. 不包含过去,现在和未来可能发生的状态变化情况 |
4. 接受无状态组件状态变化要求的通知,然后将 props 发送给他们。 | 4.从有状态组件接收 props 并将其视为回调函数。 |
React 组件的生命周期有三个不同的阶段:
- 初始渲染阶段:这是组件即将开始其生命之旅并进入 DOM 的阶段。
- 更新阶段:一旦组件被添加到 DOM,它只有在 prop 或状态发生变化时才可能更新和重新渲染。这些只发生在这个阶段。
- 卸载阶段:这是组件生命周期的最后阶段,组件被销毁并从 DOM 中删除。
事件是对鼠标悬停、鼠标单击、按键等特定操作的触发反应。处理这些事件类似于处理 DOM 元素中的事件
事件定义
事件参数中包含一组特定于事件的属性。每个事件类型都包含自己的属性和行为,只能通过其事件处理程序访问。
合成事件是围绕浏览器原生事件充当跨浏览器包装器的对象。它们将不同浏览器的行为合并为一个 API。
这样做是为了确保事件在不同浏览器中显示一致的属性。
Refs 是 React 中引用的简写
- 需要管理焦点、选择文本或媒体播放时
- 触发式动画
- 与第三方 DOM 库集成
使用 export 和 import 属性来模块化代码。它们有助于在不同的文件中单独编写组件。
React 表单类似于 HTML 表单。
在 React 中,状态包含在组件的 state 属性中,并且只能通过this.setState()
更新。
因此元素不能直接更新它们的状态,它们的提交是由 JavaScript 函数处理的。此函数可以完全访问用户输入到表单的数据。
- 受控组件:利用组件状态控制表单的值
- 非受控组件:利用节点操作控制表单的值
受控组件 | 非受控组件 |
---|---|
1. 没有维持自己的状态 | 1. 保持着自己的状态 |
2.数据由父组件控制 | 2.数据由 DOM 控制 |
3. 通过 props 获取当前值,然后通过回调通知更改 | 3. Refs 用于获取其当前值 |
高阶组件是重用组件逻辑的高级方法,它是一个纯函数,是一种源于 React 的组件模式
- 高阶组件可以接受子组件提供的任何动态,但不会修改或复制其输入组件中的任何行为,是“纯(Pure)”组件。
高阶组件形式:
高阶组作用
纯(Pure) 组件是可以编写的最简单、最快的组件。它们可以替换任何只有 render() 的组件。这些组件增强了代码的简单性和应用的性能。
key 是用于识别唯一的 Virtual DOM 元素及其驱动 UI 的相应数据
key 必须是唯一的数字或字符串
作用
- 对 DOM 操作的代价非常高
- 程序运行缓慢且效率低下
- 内存浪费严重
- 由于循环依赖性,组件模型需要围绕 models 和 views 进行创建
Flux 是一种强制单向数据流的架构模式。
作用:控制派生数据,并使用具有所有数据权限的中心 store 实现多个组件之间的通信,为应用提供稳定性并减少运行时的错误
注意:在整个应用中的数据更新必须只能在定义store处进行。
Redux 可预测状态容器,用于整个应用的状态管理。
使用 Redux 开发的应用易于测试,可以在不同环境中运行,并显示一致的行为。
单一数据来源:整个应用的状态存储在唯一一个 store 中的对象/状态树里。
单一状态树可以更容易地跟踪随时间的变化,并调试或检查应用程序。
状态是只读的:改变状态(state)的唯一方法是去触发一个动作(action)。
确保了 视图 和 网络请求 都不能直接修改 state,相反它们只能表达想要修改的意图
所有的修改都被集中化处理,且严格按照一个接一个的顺序执行,因此不用担心 竞态条件的出现。
使用纯函数进行更改:为了指定状态树如何通过操作进行转换,你需要纯函数(reducer)。纯函数是那些返回值仅取决于其参数值的函数。
Redux 使用 “Store” 将程序的整个状态存储在同一个地方。因此所有组件的状态都存储在 Store 中,并且它们从 Store 本身接收更新。
单一状态树可以更容易地跟踪随时间的变化,并调试或检查程序
- Action:是一个用来描述发生了什么事情的对象。
- Reducer :是一个确定状态将如何变化的地方。
- Store :整个程序的状态/对象树保存在Store中。
- View: 只显示 Store 提供的数据。
React 中的
Action
必须具有type
属性,该属性指示正在执行的 action 的类型。必须将它们定义为字符串常量,并且还可以向其添加更多的属性。
Action Creator
action 构造器,一个用于创建 action 的函数,主要用于简化操作
Reducer 是一个纯函数,它规定应用程序的状态怎样因响应 action而改变。
通过接受先前的状态state和action来工作,然后它返回一个新的状态。
Reducer工作流程
Store 是一个 JavaScript 对象,它可以保存程序的状态,并提供一些方法来访问状态、调度操作和注册侦听器。
应用程序的整个状态/对象树保存在单一Store存储中。因此,Redux 非常简单且是可预测的。我们可以将中间件传递到 store 来处理数据,并记录改变存储状态的各种操作。所有操作都通过 reducer 返回一个新状态。
Flux | Redux |
---|---|
1. Store 包含状态和更改逻辑 | 1. Store 和更改逻辑是分开的 |
2. 有多个 Store | 2. 只有一个 Store |
3. 所有 Store 都互不影响且是平级的 | 3. 带有分层 reducer 的单一 Store |
4. 有单一调度器 | 4. 没有调度器的概念 |
5. React 组件订阅 store | 5. 容器组件是有联系的 |
6. 状态是可变的 | 6. 状态是不可改变的 |
React 路由是一个构建在React之上的强大的路由库,有助于向应用添加新的屏幕和流。
使 URL 与网页上显示的数据保持同步
负责维护标准化的结构和行为,并用于开发单页 Web 应用
switch 可避免路由重复匹配
),其中我们将特定的子路由(
)包起来。
组件中。主题 | 常规路由 | React 路由 |
---|---|---|
参与的页面 | 每个视图对应一个新文件 | 只涉及单个HTML页面 |
URL 更改 | HTTP 请求被发送到服务器并且接收相应的 HTML 页面 | 仅更改历史记录属性 |
体验 | 用户实际在每个视图的不同页面切换 | 用户认为自己正在不同的页面间切换 |
- 类组件有
this
,有生命周期,有状态state
- 函数组件没有
this
,没有生命周期,没有状态state
函数组件的性能比类组件的性能要高
因为类组件使用的时候要实例化,而函数组件直接执行函数取返回结果即可。
注意
props
props
是外界传递过来的,状态 state
是组件本身的,状态可以在组件中任意修改Refs 是 React 提供给我们的安全访问 DOM 元素或者某个组件实例的句柄。
ref的3种绑定方式
<input ref="inputRef" />
// 调用
this.refs.inputRef
const inputRef = react.CreateRef() || useRef(null)
<input ref={inputRef} />
// 调用
this.inputRef.current || inputRef.current
<input ref={(el)=>this.inputRef || inputRef = el} />
// 调用
this.inputRef || inputRef
useState()
是什么react hooks的状态钩子
state 和 props都是普通的JavaScript对象,都具有影响渲染输出的信息。
区别
props
props
来重新渲染子组件,否则子组件的 props
以及展现形式不会改变。state
constructor
中初始化,this.setState
来修改,修改 state
属性会导致组件的重新渲染。如果需要修改this.state中的数据 必须调用this.setstate这个方法
- 书写方案1:this.setstate({},()=>{})
- 书写方案2:this.setstate(()=({}),()=>{})
注意
不要直接修改 state(状态)
state(状态) 更新是异步的
不能依赖他们的值计算下一个state(状态)
this.setState((prevState, props) => ({
xxx: prevState.xxx + props.xxx
}));
state(状态)更新会被合并
在React中受控组件的状态通常保存在组件的状态属性中,并且只能用 setState() 方法进行更新。
JavaScript XML,一种在React组件内部构建标签的类XML语法
React在不使用JSX的情况下一样可以工作,然而使用JSX可以提高组件的可读性,因此推荐使用JSX。
优点
直接更新状态,不会重新渲染组件
扩展传值符号,在ES2018中添加的(数组/可迭代对象的传播较早,ES2015)。
例如,如果this.props包含a:1和b:2,则
与以下内容相同:
扩展符号不仅适用于该用例,而且对于创建具有现有对象的大多数(或全部)属性的新对象非常方便
this.setState(prevState => {
return {foo: {...prevState.foo, a: "updated"}};
});
hooks 是
react 16.8
引入的特性,允许在非类组件中操作state 和react的其他特性。
ReactHooks的优点
React的StrictMode是一种帮助程序组件
- 在JavaScript中,
this
的值取决于当前上下文- 在React类的组件方法中,开发人员通常希望它引用组件的当前实例,因此有必要 将这些方法绑定到该类的实例
- 通常,是在构造函数中完成的
MVC模式
在分离数据(模型),UI(视图)和逻辑(控制器)的关注方面效果很好
Flux模式
使复杂的UI不再受到级联更新的困扰
可以用于实现 跨层级 的组件数据传递
- **虚拟 DOM (VDOM)**是真实 DOM 在内存中的表示
- UI 的表示形式保存在内存中,并与实际的 DOM 同步
函数组件的性能比类组件的性能要高,因为类组件使用的时候要实例化,而函数组件直接执行函数取返回结果即可。
为了提高性能,尽量使用函数组件
state
和生命周期钩子和this
。props
渲染到页面时,就是无状态组件,就属于函数组件,也被称为哑组件或展示组件。
Refs
是React
提供给我们的安全访问DOM
元素或者某个组件实例的句柄- 可以为元素添加
ref
属性然后在回调函数中接受该元素在DOM
树中的句柄,该值会作为回调函数的第一个参数返回
vuex是尤雨溪 开发的最佳实践专门用在VUE框架上的 ,redux并非react独有 ,是一个经典的状态管理设计。
高阶组件(HOC)是接受一个组件并返回一个新组件的函数。
是从 React 的组合特性中衍生出来的,称其为纯组件,因为它们可以接受任何动态提供的子组件,但不会修改或复制输入组件中的任何行为。
HOC 可以用于以下许多用例
super
并将 props
作为参数传入的作用是啥在调用
super()
方法之前,子类构造函数无法使用this
引用,ES6 子类也是如此。
将props
参数传递给super()
调用的主要原因是在子构造函数中能够通过this.props
来获取传入的props
。