React相关笔记
1.0 React数据流-state
State是一个组件的UI数据模型,是组件渲染时的数据依据
1.0 this.state.属性名
2.0 const {同名属性名} = this.state;
- setState不会立刻改变React组件中state的值.setState()是一个异步操作的过程
- setState通过引发一次组件的更新过程来引发重新绘制
- 多次setState函数调用产生的效果会合并
this.setState({
},()=>{
//异步操作结束之后的回调函数,可写可不写
})
2.0 React数据流-props
React 的单向数据流,主要的流动管道就是 props。props 本身是不可变的。组件的 props 一定来自于默认属性或通过父组件传递而来,默认属性通过 defaultProps 静态变量的方式来定义
默认属性
static defaultProps = {
//如果babel设置为es6的转码方式,会报错,因为定义静态属性不属于es6,而在es7的草案中。ES6的class中只有静态方法,没有静态属性。
}
属性类型
import PropTypes from "prop-types";
MyComponents. propsTypes = {
optionalArray: PropTypes.array,
optionalBool: PropTypes.bool,
optionalFunc: PropTypes.func,
optionalNumber: PropTypes.number,
optionalObject: PropTypes.object,
optionalString: PropTypes.string,
optionalSymbol: PropTypes.symbol,
....
}
props的使用
<ComponentName {...this.state}/>//将ComponentName组件上的state作为属性向子组件传递,利用ES6的扩展解构方式逐个拆分state传递
<ComponentName prop1={data1} prop2={data2}/>
this.props.childre && React.Children
this.props.children是每个组件默认的属性,它有三种值:undefined,object(一个子元素),array(多个子元素),通过React.Children.map可以遍历this.props.children,而不用考虑它的值是多少
class TempComponent extends Component{
render(){
return (
<ul>
React.Children.map(this.props.children,function(item.index){
return <li>{item}</li>
})
</ul>
)
}
}
class APP extends Component{
render(){
return (
<TempComponent>
<span>1</span>
<span>2</span>
<span>3</span>
</TempComponent>
)
}
}
3.0 React ref使用
React提供的这个ref
属性,表示为对组件真正实例的引用,其实就是ReactDOM.render()返回的组件实例;需要区分一下,ReactDOM.render()
渲染组件时返回的是组件实例;而渲染dom元素时,返回是具体的dom节点
ref
可以挂到任何组件上,可以挂到组件上也可以是dom元素上
在 React16 新版本中,新引入了React.createRef与 React.forwardRef两个 API,有计划移除老的 string ref,使 ref 的使用更加便捷与明确。如果你的应用已经升级到React16.3+ 版本,那就放心大胆使用 React.createRef吧,如果暂时没有的话,建议使用 callback ref 来代替string ref
string ref 使用
class TestComponent extends Component{
handleInput(){
const ipt = this.refs.input.value;
}
render(){
return (
<input ref="input"/>
)
}
}
Callback ref使用
class TestComponent extends Component{
handleInput(){
//获取input输入框的值
const ipt = this.MyInput.value;
}
render(){
return (
<input ref="input" ref={(el)=>{
//el指待当前元素
this.MyInput = el;
}}/>
)
}
}
Reat.createRef使用
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
handleFocus(){
this.myRef.current.focus();//当ref引用的是DOM元素时候
this.myRef.current.focusTextInput();//当ref应用的是React组件的时候
}
render() {
return <div ref={this.myRef} />;
return <CustomInput ref={this.myRef}/>
}
}
4.0 React生命周期

4.0 元素绑定函数的几种方式
构造函数中绑定事件
class MyComponent extens COmponent{
constructor(props){
super(props)
this.handleInput = this.handleInput.bind(this);
}
render(){
return(
<div>
<input onChange={this.handleInput}/>
</div>
)
}
}
元素中绑定事件
class MyComponent extens COmponent{
render(){
return(
<div>
//<input onChange={this.handleInput.bind(this,"arg...")}/>
//<input onChange={::this.handleInput}/>没有参数的情况下的绑定形式
</div>
)
}
}
箭头函数形式绑定元素
class MyComponent extens COmponent{
render(){
return(
<div>
<input onChange={(e)=>{this.handleInput}}/>
</div>
)
}
}
5.0 表单操作
此部分内容摘录自《深入React技术栈》
受控组件
受控组件一般出现在表单中,每当表单元素的状态发生变化时,都会被写入到组件的 state 中,这种组件在.React 中被称为受控组件(controlled component)
React受控组件更新state的流程
- 可以通过在初始 state 中设置表单的默认值。
- 每当表单的值发生变化时,调用 onChange 事件处理器。
- 事件处理器通过合成事件对象 e 拿到改变后的状态,并更新应用的 state。
- setState 触发视图的重新渲染,完成表单组件值的更新。
非受控组件
- 如果一个表单组件没有value props(单选按钮和复选按钮对应的是 checked props)时,就可以称为非受控组件;
- 使用defaultValue和defaultChecked来表示组件的默认状态;
- 通过 defaultValue和defaultChecked来设置组件的默认值,它仅会被渲染一次,在后续的渲染时并不起作用
受控&非受控对比
- 在受控组件中,每次表单的值发生变化,都会调用一次onChange事件处理器,这确实会带来性能上的的损耗,虽然使用费受控组件不会出现这些问题,但仍然不提倡使用非受控组件
- 用受控组件需要为每一个组件绑定一个change事件,并且定义一个事件处理器来同步表单值和组件的状态,这是一个必要条件.
表单属性
状态属性
- value: 类型为text的input组件,textarea组件以及select组件都借助value prop来展示应用的状态
- checked: 类型为radio或checkbox的组件借助值为boolean类型的selected prop来展示应用的状态
- selected: 该属性可作用于select组件下面的option上,React并不建议这种方式表示状态.而推荐在select组件上使用value的方式
事件属性
- 当状态属性改变时会触发onChange事件属性.受控组件中的change事件与HTML DOM中提供的input事件更为类似;
6.0 组件间通信的方式
父组件传递数据到子组件
父组件通过 props 向子组件传递需要的信息
子组件传递数据到父组件
class Parent extends Component{
constructor(){
super()
this.state = {a:1}
}
handlePassData(argsFromChild){
this.setState({
this.state:argsFromChild
})
}
render(){
return(
<Child ParentEventProp={this.handlePassData.bind(this)} />
<div>{this.state.a}</div>
)
}
}
class Child extends Components{
...
render(){
return(
<input onChange={(el)=>{this.props.ParentEventProp(el.value) } />
)
}
}
嵌套跨级组件间通信
所谓跨级组件通信,就是父组件向子组件的子组件通信,向更深层的子组件通信,通常有两种方式:
- 中间组件层层传递 props
- 使用 context 对象
无嵌套组件间数据通信
7.0 React组件性能优化
纯函数 & UI组件(无状态组件)
纯函数的特点:
- 给定相同的输入,它总是返回相同的输出;
- 过程没有副作用(side effect),不会对外部数据进行篡改
- 不会产生对外部数据的依赖
UI组件的数据值都是通过父组件的props传递过来,与交互相关的逻辑也都写在父组件,父组件也可以称作UI组件的容器组件,负责子组件的逻辑处理,数据传递和修改,UI组件因为免去了组件的生命周期函数部分的执行,提高了组件渲染的性能
const UIComponent = (props)=>{
render(){
const {handleClick,stateFromParent} = {this.props}
return(
<div onClick={handleClick}>{stateFromParent}</div>
)
}
}
shouldComponentUpdate的合理运用
在纯函数的基础上衍生你的 PureRender,PureRender 中的 Pure 指的就是组件满足纯函数的条件,即组件的渲染是被相同的 props 和 state 渲染进而得到相同的结果。这个概念与上述给定相同的输入,它总是返回相同的输出一致。
可能会有这样的情况:父组件的数据(和子组件无关)修改导致父组件的render函数执行,而包裹在父组件的组件内虽然没有数据更新,但是也会执行子组件内部的render函数,造成了性能损耗。
//通过在子组件以下的生命周期函数中返回false则子组件不会被重新渲染
shouldComponentUpdate(nextProps, nextState) {
// 如果进行深度的比较当前值和父组件重新渲染赋予的属性值会造成很大的性能损耗
return DeepCompare(this.props, nextProps) &&
DeepCompare(this.state, nextState);
}
PureRender 的原理为重新实现了 shouldComponentUpdate 生命周期方法,让当前传入的 props和 state 与之前的作浅比较,如果返回 false ,那么子组件就不会执行 render 方法,即即使父组件执行了render但是子组件不会发生重新渲染.提高react性能.
import PureRenderMixin from 'react-addons-pure-render-mixin';
class App extends Component {
constructor(props) {
super(props);
this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
}
render() {
return <div className={this.props.className}>foo</div>;
}
}
其他React性能优化整理
- 组件中的属性值都用常量赋值,不要直接填充对象,比如在render函数中用
render(){ const { Variablel,Function} = this.props return( <Child>{Variable}</Child> <div onClick = {Function}></div> ) }
- 事件函数绑定最好选在constructor中进行this的指向,因为它只进行一次绑定
性能检测工具
在React 16以前使用react-addons-perf对React组件的性能进行监控,React16以后直接使用 Chrome Performance Tab /Profiling Components with the Chrome Performance Tab
网友评论