React生态
2020-06-15 11:32:42 2 举报
AI智能生成
React基础知识总结
作者其他创作
大纲/内容
路由
react-router
react-router-redux
环境配置
NodeJs
Webpack
构建工具
WebPack
配置代理
配置示例
子主题
概念
前端资源加载/打包工具
可以将多种静态资源js、css、less转换成一个静态文件
减少页面请求
减少页面请求
安装
npm install webpack -g
Loader
webpack本身只能处理JavaScript模块,
如果要处理其他模块,需要使用loader转换
如果要处理其他模块,需要使用loader转换
子主题
dev-server
参数
target
要使用url模块解析的url字符串
forward
要使用url模块解析的url字符串
agent
要传递给http(s).request的对象
ssl
要传递给https.createServer()的对象
ws
是否代理websockets
xfwd
是否添加x-forward标头
secure
是否验证后端服务器SSL Certs
toProxy
传递绝对URL作为路径(对代理代理很有用)
prependPath
指定是否要将目标的路径添加到代理路径
ignorePath
指定是否要忽略传入请求的代理路径(注意:如果需要,您必须附加/手动)
localAddress
要为传出连接绑定的本地接口字符串
changeOrigin
将主机标头的原点更改为目标URL
默认值
false
gulp
常用类库
axios
封装XmlHttpRequest对象的ajax
react router
提供了一些router的核心api,包括Router, Route, Switch等,但是它没有提供dom操作进行跳转的api。
mobx
Ant Design of React
redux
material-ui
immutable-js
draft-js
css-modules
react-devtools
Babel
TypeScript
UI库
material-ui
react-toolbox
ant design
技术栈的选择
后台应用
react+dva+ant design (五星)
react+dva+bfd-ui (四星半)
react+react-router+redux+webpack+ant design (四星)
react+react-router+mobx+webpack+bfd-ui/ant design (三星半)
react+react-router+redux+webpack+bfd-ui (三星)
前台web应用
react+dva+material-ui/react-toolbox (四星半)
react+dva+bfd-ui/ant design (四星)
概念
Facebook开源了React,这是该公司用于构建反应式图形界面的JavaScript库,已经应用于构建Instagram网站及 Facebook部分网站。
最近出现了AngularJS、MeteorJS 和Polymer中实现的Model-Driven Views等框架,React也顺应了这种趋势。React基于在数据模型
之上声明式指定用户界面的理念,用户界面会自动与底层数据保持同步。与前面提及 的框架不同,出于灵活性考虑,React使用JavaScript
来构建用户界面,没有选择HTML
最近出现了AngularJS、MeteorJS 和Polymer中实现的Model-Driven Views等框架,React也顺应了这种趋势。React基于在数据模型
之上声明式指定用户界面的理念,用户界面会自动与底层数据保持同步。与前面提及 的框架不同,出于灵活性考虑,React使用JavaScript
来构建用户界面,没有选择HTML
优缺点
优点
声明式
以前都是自己亲自操作dom,有了声明式,就是我们不用亲自做,只需去操作数据
组件化
就是从UI的角度去分析;把一个页面去拆成互不相干的小组件
模块化
就是以代码的角度去分析问题;把我们的编程时候的业务逻辑
分割到不同的模块来进行开发,可以使代码重用,变量不会污染
分割到不同的模块来进行开发,可以使代码重用,变量不会污染
高效
虚拟Dom
编码时只需要操作React虚拟DOM的相关数据,React会转化为
真实dom变化更新界面,最大限度减少与DOM的交互
真实dom变化更新界面,最大限度减少与DOM的交互
diff算法
单向数据流
减少重复代码,组件的数据只要唯一的入口和出口,
让组件更直观更容易理解使得组件更容易维护
让组件更直观更容易理解使得组件更容易维护
。。。。。
缺点
ReactJS组件难以在复杂交互页面中复用
如果使用不当,ReactJS的虚拟DOM 算法又慢又不准
。。。。
安装
1.通过create-react-app快速构建React开发环境
1.npx create-react-app my-app
2.cd my-app
3.npm start
2.cd my-app
3.npm start
2.直接引用
3.官方CDN引用
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<!-- 生产环境中不建议使用 -->
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<!-- 生产环境中不建议使用 -->
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
注意:在浏览器中使用Babel编译JSX效率非常低
示例
4.npm安装
目录结构
manifest.json 指定了开始页面 index.html,一切的开始都从这里开始,所以这个是代码执行的源头
语法和结构
元素
元素是构成 React 应用的最小单位,它用于描述屏幕上输出的内容
const element = <h1>Hello, world!</h1>;
与浏览器的DOM元素不同,React 当中的元素事实上是普通的对象,
React DOM可以确保浏览器DOM的数据内容与React元素保持一致
React DOM可以确保浏览器DOM的数据内容与React元素保持一致
const element = <h1>Hello, world!</h1>;
React 元素都是不可变的。当元素被创建之后,你是无法改变其内容或属性的,
更新界面的唯一办法是创建一个新的元素,然后将它传入 ReactDOM.render() 方法
更新界面的唯一办法是创建一个新的元素,然后将它传入 ReactDOM.render() 方法
示例1
示例2
示例3
JSX
优点
1.执行更快,因为在编译为JavaScript代码后进行了优化
2.类型安全,在编译过程中就能发现错误
3.使用JSX编写模板更加简单快速
备注
用来声明React当中的元素
表达式
示例
样式
示例
注释
示例
数组
示例
注意点
1.JSX中的元素添加自定义属性,需要使用data-前缀
2.JSX不能使用if else语句,可以使用conditional表达式来表达
3.推荐使用内联样式
组件
1.函数定义组件
示例
2.ES6 class定义组件
示例
3.复合组件
示例
创建多个组件来合成一个组件,即把组件的不同功能点进行分离
4.用户自定义组件
示例
5.无状态函数式组件
参数是props,意味着不需要用this来访问
注意
1.原生html元素以小写字母开头,而自定义的React类目以大写字母开头
2.组件类只能包含一个顶层标签,否则会报错
3.向组件传递参数,可以使用this.props对象
4.class属性写成className,for属性需要写成htmlFor
状态
state
React把组件看成是一个状态机
示例
代码执行顺序
props
与state的主要区别在于props是不可变的,而state可以根据与用户交互来改变
简单示例
默认Props
可以通过组件类的defaultProps属性为props设置默认值
示例
如果是React.createClass()形式,则定义一个getDefaultProps()的对象键
示例
如果是ES7写法,则可以定义static方法
示例
state和props的组合使用
示例
Props验证
注意
1.React.PropTypes在React v15.5 版本后已经移到了prop-types库
React.PropTypes 提供很多验证器 (validator) 来验证传入数据是否有效
示例
验证器
示例
当前常用示例
示例
数据自顶向下流动/单向数据流
1.父组件或子组件都不能知道某个组件是有状态还是无状态,
并且它们不应该关心某组件是被定义为一个函数还是一个类
并且它们不应该关心某组件是被定义为一个函数还是一个类
这就是为什么状态被称为局部或封装
除了拥有并设置它的组件外,其他组件不可访问
任何状态始终由某些特定组件所有,并且从该状态导出的任何数据或 UI
只能影响树中下方的组件。如果你想象一个组件树作为属性的瀑布,
每个组件的状态就像一个额外的水源,它连接在一个任意点,但也流下来
只能影响树中下方的组件。如果你想象一个组件树作为属性的瀑布,
每个组件的状态就像一个额外的水源,它连接在一个任意点,但也流下来
示例
该示例中每个Clock组件都建立了自己的定时器并独立更新
事件处理
基本介绍
采用 JSX 的语法你需要传入一个函数作为事件处理函数,而不是一个字符串(DOM 元素的写法)
React 事件绑定属性的命名采用驼峰式写法,而不是小写
向事件处理程序传递参数
通过箭头函数的方式,事件对象必须显式的进行传递,但是通过 bind 的方式,事件对象以及更多的参数将会被隐式的进行传递。
值得注意的是,通过 bind 方式向监听函数传参,在类组件中定义的监听函数,事件对象 e 要排在所传递参数的后面
值得注意的是,通过 bind 方式向监听函数传参,在类组件中定义的监听函数,事件对象 e 要排在所传递参数的后面
向事件处理程序传递参数
1.<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
箭头函数,参数e作为React 事件对象将会被作为第二个参数进行传递。通过箭头函数的方式,事件对象必须显式的进行传递
2.<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
事件对象以及更多的参数将会被隐式的进行传递
注意
值得注意的是,通过 bind 方式向监听函数传参,
在类组件中定义的监听函数,事件对象 e 要排在所传递参数的后面
在类组件中定义的监听函数,事件对象 e 要排在所传递参数的后面
React 事件中 this 的三种使用方式
1.bind绑定的方法
不传参
传参
2.属性初始化器
不传参
传参
3.回调函数的方式
不传参
传参
事件处理器中this引用的总是事件处理器所处的组件,因为React自动绑定一个
组件中所有方法给this,这种自动绑定的行为只适用于当组件是用React.createClass
创建时,如果用ES6的类来定义组件,那么事件处理器中this的值是undefined,
除非你显示绑定它
组件中所有方法给this,这种自动绑定的行为只适用于当组件是用React.createClass
创建时,如果用ES6的类来定义组件,那么事件处理器中this的值是undefined,
除非你显示绑定它
注意
1.不能使用返回false的方式阻止默认行为,
必须明确的使用preventDefault
必须明确的使用preventDefault
2.你必须谨慎对待 JSX 回调函数中的 this,类的方法默认是不会绑定 this 的。
如果你忘记绑定 this.handleClick 并把它传入 onClick, 当你调用这个函数的时候
this 的值会是 undefined。通常情况下,如果你没有在方法后面添加 () ,
例如 onClick={this.handleClick},你应该为这个方法绑定 this
如果你忘记绑定 this.handleClick 并把它传入 onClick, 当你调用这个函数的时候
this 的值会是 undefined。通常情况下,如果你没有在方法后面添加 () ,
例如 onClick={this.handleClick},你应该为这个方法绑定 this
解决方法
1.属性初始化
2.箭头函数
使用这个语法有个问题就是每次 LoggingButton 渲染的时候都会创建一个不同的回调函数。
在大多数情况下,这没有问题。然而如果这个回调函数作为一个属性值传入低阶组件,
这些组件可能会进行额外的重新渲染。我们通常建议在构造函数中绑定或使用属性初始化器语法来避免这类性能问题。
在大多数情况下,这没有问题。然而如果这个回调函数作为一个属性值传入低阶组件,
这些组件可能会进行额外的重新渲染。我们通常建议在构造函数中绑定或使用属性初始化器语法来避免这类性能问题。
合成事件
1.在React中,如果像onClick中所做的那样在JSX中指定事件时
是不能直接处理常规的DOM事件的,而是处理React特定的事件类型SyntheticEvent
是不能直接处理常规的DOM事件的,而是处理React特定的事件类型SyntheticEvent
2.事件处理器不能得到原生的事件参数类型MouseEvent/KeyboardEvent等等,
而是总是得到封装了浏览器原生事件的事件参数类型SyntheticEvent
而是总是得到封装了浏览器原生事件的事件参数类型SyntheticEvent
SyntheticEvent
公共属性
boolean bubbles
boolean cancelable
DOMEventTarget currentTarget
boolean defaultPrevented
number eventPhase
boolean isTrusted
DOMEvent nativeEvent
void preventDefault()
void stopPropagation()
DOMEventTarget target
string type
特殊属性
MouseEvent
属性
KeyboardEvent
属性
注意
当使用合成事件及其属性时,不要参考传统 DOM 事件文档。
因为 SyntheticEvent 包含了原生 DOM 事件,事件及其属性并不一定
是一对一映射的。有些 DOM 事件在 React 甚至是不存在的
因为 SyntheticEvent 包含了原生 DOM 事件,事件及其属性并不一定
是一对一映射的。有些 DOM 事件在 React 甚至是不存在的
官方事件文档链接
对于React官方不能识别的事件,还必须用传统的addEventListener,
在componentDidMount添加事件,在componentWillUnmount中remove
在componentDidMount添加事件,在componentWillUnmount中remove
React决定背离处理传统DOM事件的原因
1.浏览器兼容性
2.性能提升
条件渲染
1.元素变量
示例
2.与运算符 &&
示例
3.三目运算符
示例
4.阻止组件渲染
在极少数情况下,你可能希望隐藏组件,即使它被其他组件渲染。
让 render 方法返回 null 而不是它的渲染结果即可实现
让 render 方法返回 null 而不是它的渲染结果即可实现
示例
列表与keys
1.使用 JavaScript 的 map() 方法来创建列表
示例
2.Keys 可以在 DOM 中的某些元素被增加或删除的
时候帮助 React 识别哪些元素发生了变化。因此你
应当给数组中的每一个元素赋予一个确定的标识
时候帮助 React 识别哪些元素发生了变化。因此你
应当给数组中的每一个元素赋予一个确定的标识
数据有唯一值
示例
数据没有唯一,用索引index作为key
示例
注意
如果列表可以重新排序,我们不建议使用索引来进行排序,因为这会导致渲染变得很慢
元素的 key 只有在它和它的兄弟节点对比时才有意义。
比方说,如果你提取出一个 ListItem 组件,你应该把 key 保存
在数组中的这个 <ListItem /> 元素上,而不是放在 ListItem 组件中的 <li> 元素上
比方说,如果你提取出一个 ListItem 组件,你应该把 key 保存
在数组中的这个 <ListItem /> 元素上,而不是放在 ListItem 组件中的 <li> 元素上
示例
错误示范
正确示范
元素的 key 在他的兄弟元素之间应该唯一,不需要全局唯一
示例
JSX允许在大括号中嵌入任何表达式,需要注意
示例
组件API
1.设置状态 setState
setState(object nextState[, function callback])
nextState,将要设置的状态,会和当前的state合并
callback,可选参数,回调函数,当setState成功,且组件重新渲染后调用
参数1是个对象,或者是一个函数,但是函数内部必须返回一个对象
Demo
setState是React事件处理函数中和请求回调函数中触发UI更新的主要方法
注意
1.setState()并不会立即改变this.state,而是创建一个即将处理的state。
setState()并不一定是同步的,为了提升性能React会批量执行state和DOM渲染
setState()并不一定是同步的,为了提升性能React会批量执行state和DOM渲染
2.setState()总是会触发一次组件重绘,除非在shouldComponentUpdate()中
实现了一些条件渲染逻辑
实现了一些条件渲染逻辑
3.不要直接更新状态,要使用setState
错误
正确
4.构造函数是唯一能够初始化 this.state 的地方,ES7例外
5.状态更新可能是异步的
React 可以将多个 setState() 调用合并成一个调用来提高性能。
因为 this.props 和 this.state 可能是异步更新的,你不应该依
靠它们的值来计算下一个状态
因为 this.props 和 this.state 可能是异步更新的,你不应该依
靠它们的值来计算下一个状态
错误
正确
6.状态更新合并
当你调用 setState() 时,React 将你提供的对象合并到当前状态
2.替换状态 replaceState
replaceState(object nextState[, function callback])
nextState,将要设置的新状态,该状态会替换当前的state。
callback,可选参数,回调函数。该函数会在replaceState设置
成功,且组件重新渲染后调用
成功,且组件重新渲染后调用
与setState()类似,但是方法只会保留nextState中状态,原state不在nextState中的状态都会被删除
3.设置属性 setProps
setProps(object nextProps[, function callback])
nextProps,将要设置的新属性,该状态会和当前的props合并
callback,可选参数,回调函数。该函数会在setProps设置成功,
且组件重新渲染后调用
且组件重新渲染后调用
使用场合
更新组件,我可以在节点上再次调用React.render(),也可以通过setProps()方法改变组件属性,触发组件重新渲染
4.替换属性 replaceProps
replaceProps(object nextProps[, function callback])
nextProps,将要设置的新属性,该属性会替换当前的props
callback,可选参数,回调函数。该函数会在replaceProps设置成功,
且组件重新渲染后调用
且组件重新渲染后调用
replaceProps()方法与setProps类似,但它会删除原有 props
5.强制刷新 forceUpdate
forceUpdate([function callback])
callback,可选参数,回调函数。该函数会在组件render()方法调用后调用
使用场合
forceUpdate()方法会使组件调用自身的render()方法重新渲染组件,组件的子组件也会调用自己的render()
注意
应该尽量避免使用forceUpdate(),而仅从this.props和this.state中读取状态并由React触发render()调用
6.获取DOM节点 findDOMNode
DOMElement findDOMNode()
返回值:DOM元素DOMElement
注意点
如果组件已经挂载到DOM中,该方法返回对应的本地浏览器 DOM 元素
使用场合
从DOM 中读取值的时候,该方法很有用,
如:获取表单字段的值和做一些 DOM 操作
如:获取表单字段的值和做一些 DOM 操作
7.判断组件挂载状态 isMounted
bool isMounted()
返回值:true或false,表示组件是否已挂载到DOM中
使用场合
可以使用该方法保证了setState()和forceUpdate()在异步场景下的调用不会出错
注意
在ES6中已经废除
原因是它经过实际使用与测试可能不足以检测组件是否挂载,尤其是对于有一些异步的程序情况,以及逻辑上造成混乱
代替方法
componentDidMount() {
this.mounted = true;
}
componentWillUnmount() {
this.mounted = false;
}
this.mounted = true;
}
componentWillUnmount() {
this.mounted = false;
}
react组件生命周期
getDefaultProps
示例
getInitialState
componentWillMount
组件将要加载
render
组件渲染
componentDidMount
组件加载完成,用于请求接口
如果你想和其他JavaScript框架一起使用,可以在这个方法中
调用setTimeout, setInterval或者发送AJAX请求等操作(防止异步操作阻塞UI)
调用setTimeout, setInterval或者发送AJAX请求等操作(防止异步操作阻塞UI)
componentWillReceiveProps
组件状态将要发生改变
在组件接收到一个新的 prop (更新后)时被调用。
这个方法在初始化render时不会被调用
这个方法在初始化render时不会被调用
shouldComponentUndate
组件状态更新
返回一个布尔值。在组件接收到新的props或者state时被调用。
在初始化时或者使用forceUpdate时不被调用。
在初始化时或者使用forceUpdate时不被调用。
使用场景
可以在你确认不需要更新组件时使用
componentWillUpdate
组件将要更新
在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用
componentDidUpdate
组件更新完成
在组件完成更新后立即调用。在初始化时不会被调用
componentWillUnmount
组件卸载
在组件从 DOM 中移除之前立刻被调用
三个状态
Mouting(已插入真实DOM)
Updating(正在被重新渲染)
Unmouting(已移除真实DOM)
示例
执行顺序
首次加载渲染Initial Render
1.getDefaultProps
设置默认值
组件被创建或者父组件的任务属性传递进来之前调用
2.getInitialState
组件被创建前设置this.state的默认值
3.componentWillMount
组件被渲染到DOM之前被调用的最后一个方法
在此方法中调用setState,组件不会被重新渲染
4.render
如果不想渲染任务东西,直接返回null或者false即可
5.componentDidMount
可以安全的执行任何 DOM 查询操作
更新阶段State Change
1.shouldComponentUpdate
控制更新
true
组件会更新
false
组件不会更新
参数
newProps
newState
2.componentWillUpdate
组件被更新之前调用
不能在这个方法中通过调用this.setState来修改状态
3.render
如果没有通过 shouldComponentUpdate 忽略更新,
那么 render 中的代码会再次被调用,以确保组件正确显示自己
那么 render 中的代码会再次被调用,以确保组件正确显示自己
4.componentDidUpdate
组件更新以及render方法被调用过后被调用
如果要在更新发生后执行一些代码,那么应该把代码放在这个方法中
处理prop改变Props Change
1.componentWillReceiveProps
该方法只返回一个参数,并且该参数包含将要赋值的新 prop 值
2.shouldComponentUpdate
3.componentWillUpdate
4.render
5.componentDidUpdate
组件卸载Unmount
1.componentWillUnmount
在这个方法中执行清理相关的任务,比如移除事件监听器、停止计数器等等
React Ajax
组件的数据可以通过 componentDidMount 方法中的 Ajax 来获取,
当从服务端获取数据时可以将数据存储在 state 中,再用 this.setState 方法重新渲染 UI
当从服务端获取数据时可以将数据存储在 state 中,再用 this.setState 方法重新渲染 UI
当使用异步加载数据时,在组件卸载前使用 componentWillUnmount 来取消未完成的请求
Demo
React表单与事件
HTML 表单元素与 React 中的其他 DOM 元素有所不同,
因为表单元素生来就保留一些内部状态
因为表单元素生来就保留一些内部状态
多个表单
当你有处理多个 input 元素时,你可以通过
给每个元素添加一个 name 属性,来让处理
函数根据 event.target.name 的值来选择做什么
给每个元素添加一个 name 属性,来让处理
函数根据 event.target.name 的值来选择做什么
Demo
button事件
Demo
React Refs
这个特殊的属性允许你引用 render() 返回的相应的
支撑实例( backing instance )。这样就可以确保
在任何时间总是拿到正确的实例
支撑实例( backing instance )。这样就可以确保
在任何时间总是拿到正确的实例
Demo
DOM挂载与卸载
ReactDOM.render()
两个参数,内容和渲染目标js对象
ReactDOM.unmountComponentAtNode(div);
React数据传递
父传子
定义props向下级传递
子传父
子组件调用父组件方法触发父组件
父组件定义方法接收方法修改本组件定义的state
兄弟间组件调用
react的diff运算
数据方向单向数据流
数据状态每次更新,组件都会进行运算,发生改变的状态更新
状态管理
state
props
redux
特性
响应动作和事件
适合复杂的应用,大团队,需求变化多
一般被认为是应用程序中所有状态的中间人
组件之间不会直接通讯,而是所有状态改变必须经过单一数据源-store
发起改变的组件只需要关心将改变分发到store
三大原则
1.单一数据源
一个store存储应用程序的所有状态
2.状态是只读的
修改状态的唯一方法是触发一个 action,即一个描述发生了什么的对象
不能直接修改状态,而是通过分发action,来表达要改变store中状态的意图
3.使用纯函数来执行修改
Reducer 是用户编写的函数,可以直接修改状态
会把当前状态作为参数,并且只能通过返回新的状态来修改状态
示例
reducer 必须被写为纯函数
纯函数的特征
1.它不会发起对外部网络或者数据库的调用
2.其返回值完全依赖于其参数值
3.其参数应该被当作是不可修改的,就是说不能被修改
4.调用参数相同的纯函数总是返回相同的值
API
store.dispatch(action)
store.subscribe(listener)
store.getState()
replaceReducer(nextReducer)
概念语法
reducers
action
connect
使用方法
示例
1.创建带有一个 reducer 的 store
2.reducer 设置应用程序的初始状态为一个空数组
3.分发一个 action,这个 action 是用来添加一个新用户
4.reducer 将新用户添加到状态上,并返回新的状态,这会更新 store
技巧
1.使对象不可变的技巧
1.var newState=Object.assign({},state,{foo:123});
2.const newState={...state,foo:123}
3.其他方式,比如Immutable.js
react-redux
示例
这里看到 connect()() 带有两对括号可能有点怪异。这实际上是两次函数调用。第一对括号是为了让 connect() 返回另一个函数。当然,我们可以把该函数赋值给一个名称,然后调用它。但是既然我们可以用第二对括号立即调用它,那么这么做有何必要呢?而且,反正在第二个函数被调用之后,我们没有理由需要第二个函数名的存在。当然,第二个函数需要你传递一个 React 组件。在本例中这个组件是我们的容器组件。 我理解你会想“为什么要搞的这么复杂”,但是这实际上是一个常见的函数式编程范式,所以你就学它好了
connect() 的第一个参数是一个函数,该函数必须返回一个对象。这个对象的属性必须成为组件上的 "props"。你可以看到它们的值来自于状态
Flux
Redux使用一个store,Flux使用多个store,这是二者间的主要区别
Mobx
特性
适合做一些简单的应用,原型实验,适合小的团队使用
响应状态的变化
概念语法
@action
触发事件改变state值
@obseverble
定义初始化值数据
dva
基于redux, react-router打造
处理了很多包括项目构建,异步处理、统一请求、统一错误处理等一系列诸多问题
Flux
组件解耦优化
容器组件
获取数据并处理状态
一般为展示型组件的父组件
充当展示性组件和应用程序其它部分之间的一个中介
不创建任何渲染它们自己的东西,而是返回展示性组件的结果
一般没有任何样式
展示型组件
只是用来接收数据并展示结果
1.不会修改prop数据,接收的数据是不可变的
2.可以格式化化数据并展示
Demo
展示容器组件上的事件如何修改状态,从而会自动更新展示性组件
极少有自己的状态(如果有的话,就是 UI 状态,而不是数据)
高阶组件
Constructor
逻辑function使用
无状态组件
const abc=()=>{return ()}
调用父组件传递的props方法
有状态组件
class功能性组件
使用()=> 由ES6箭头函数指定
不在执行的render中调用setState,会进入死循环
定义bind绑定到当前组件
this.setState使用
基本用法:改变本组件状态
特殊用法:本方法需要同步执行时调用第二个回调参数
三大属性
1.state
备注
2.props
备注
3.refs与事件处理
备注
props和state的区别
备注
React Router
Router
Route
path
component
onEnter
权限验证
onLeave
IndexRoute
不使用的话
示例
使用React Router
示例
简介
React Router 是一个基于 React 之上的强大路由库,它可以让你向
应用中快速地添加视图和数据流,同时保持页面与 URL 间的同步
应用中快速地添加视图和数据流,同时保持页面与 URL 间的同步
history
browserHistory
hashHistory
createMemoryHistory
最佳实践
1.多用 Function Component
场景
如果组件是纯展示型的,不需要维护 state 和生命周期
优势
代码更简洁
更好的复用性
更小的打包体积,更高的执行效率
示例
2.多用 PureComponent
Component 的默认行为是不论 state 和 props 是否有变化,都触发 render
PureComponent 会先对 state 和 props 进行浅比较,不同的时候才会 render
3.遵循单一职责原则,使用 HOC / 装饰器 / Render Props 增加职责
示例
比如一个公用的组件,数据来源可能是父组件传过来,又或者是自己主动通过网络请求获取数据。这时候可以先定义一个纯展示型的 Function Component,然后再定义一个高阶组件去获取数据
4.组合优于继承
继承会让代码难以溯源,定位问题也比较麻烦。所有通过继承实现的组件都可以改写为组合的形式
5.避免在 render 里面动态创建对象 / 方法,否则会导致子组件每次都 render
示例
6.避免在 JSX 中写复杂的三元表达式,应通过封装函数或组件实现
三元表达式可读性差
7.多使用解构,如 Function Component 的 props
8.定义组件时,定义 PropTypes 和 defaultProps
示例
9.避免使用无谓的标签和样式
10.空行区分自己的依赖
示例
11.给setState传入一个函数作为参数
原因
setState实际是异步执行的,react因为性能原因会将state的变化整合,
再一起处理,因此当setState被调用的时候,state并不一定会立即变化
再一起处理,因此当setState被调用的时候,state并不一定会立即变化
方案
setState传入一个方法,该方法接收上一次的state作为参数
this.setState(prevState => ({ expanded: !prevState.expanded })
12.避免向子组件传入闭包
示例
原因
每次父组件重新渲染时,都会创建一个新的函数,并传给input,
如果这个input是个react组件的话,这会导致无论该组件的其他属性是否变化,该组件都会重新render
如果这个input是个react组件的话,这会导致无论该组件的其他属性是否变化,该组件都会重新render
13.函数组件中不要使用ES6箭头函数写法
错误示例
const ExpandableForm = ({ onExpand, expanded, children }) => {}
原因
这种写法中,函数实际是匿名函数,运行时出错不方便调试
推荐使用function,而不是const
推荐使用function,而不是const
14.函数组件中態使用装饰器,可以将其作为入参传给observer函数
示例
15.在JSX中使用条件判断(Conditionals in JSX)
条件判断太多时,可以使用立即执行函数的方式来解决问题,将if语句放到立即执行函数中,返回任务你想返回的
立即执行函数会带来一定的性能问题,但是对于代码的可读性来说,这个影响可以忽略
错误示例
推荐写法
立即执行函数示例
16.组件的state中不能出现props
错误示例
正确示例
17.保持state的简洁,不要出现计算得来的state
错误示例
错误示例
18.不要把display logic写在componentWillReceiveProps或componentWillMount中,把它们都移到render()中去
完整结构
class
示例
函数组件
示例
React Hooks
useState
示例
子主题
useRef
useReducer
0 条评论
下一页