Skip to content

React 进阶 #100

@coconilu

Description

@coconilu

概述

  1. 表单
    • 受控组件
    • 非受控组件
  2. 合成事件
    • 事件池
    • 支持的事件
  3. 对比算法
  4. API
    • React
    • ReactDOM
    • ReactServer

表单

受控组件

值由React控制的输入表单元素称为“受控组件”。组件的value属性关联组件的状态,然后组件的onChange句柄会更新组件的状态。

非受控组件

在大多数情况下,我们推荐使用 受控组件 来实现表单。 在受控组件中,表单数据由 React 组件处理。如果让表单数据由 DOM 处理时,替代方案为使用非受控组件。

借助ref我们可以引用到经过React渲染后的真实元素。

默认值

<input type="checkbox"><input type="radio"> 支持 defaultChecked
<input type="text"><select><textarea> 支持 defaultValue

文件输入标签

在React中,<input type="file" /> 始终是一个不受控制的组件。应该使用File API与文件进行交互。

合成事件(SyntheticEvent)

在React里,事件处理函数会接收SyntheticEvent的实例,一个基于浏览器原生事件的跨浏览器实现。它拥有和浏览器原生事件一样的接口,包括stopPropagation()preventDefault(),除了那些所有浏览器功能一样的事件。

boolean bubbles
boolean cancelable
DOMEventTarget currentTarget
boolean defaultPrevented
number eventPhase
boolean isTrusted
DOMEvent nativeEvent,底层的浏览器事件
void preventDefault()
boolean isDefaultPrevented()
void stopPropagation()
boolean isPropagationStopped()
DOMEventTarget target
number timeStamp
string type

由于在v0.14版本中,事件处理函数返回false不会再阻止事件传播, 所以必须得手动触发e.stopPropagation()e.preventDefault() 方法。

事件池

SyntheticEvent是共享的。那就意味着在调用事件回调之后,SyntheticEvent对象将会被重用,并且所有属性会被置空。这是出于性能因素考虑的。 因此,您无法以异步方式访问事件。

但是可以通过event.persist()方法来防止被置空。

支持的事件

下面的事件处理函数由冒泡阶段的事件触发。在事件名后面加Capture就能在事件捕获阶段注册事件处理函数。

Clipboard Events

事件名:

onCopy onCut onPaste

属性:

DOMDataTransfer clipboardData

Composition Events

事件名:

onCompositionEnd onCompositionStart onCompositionUpdate

属性:

string data

Keyboard Events

事件名:

onKeyDown onKeyPress onKeyUp

属性:

boolean altKey
number charCode
boolean ctrlKey
boolean getModifierState(key)
string key
number keyCode
string locale
number location
boolean metaKey
boolean repeat
boolean shiftKey
number which

Focus Events

事件名:

onFocus onBlur

这些焦点事件适用于React DOM中的所有元素,而不仅仅是表单元素。

属性:

DOMEventTarget relatedTarget

Form Events

事件名:

onChange onInput onSubmit

Mouse Events

事件名:

onClick onContextMenu onDoubleClick onDrag onDragEnd onDragEnter onDragExit
onDragLeave onDragOver onDragStart onDrop onMouseDown onMouseEnter onMouseLeave
onMouseMove onMouseOut onMouseOver onMouseUp

onMouseEnter 和 onMouseLeave 事件由失去焦点的元素到正在输入的元素传播,并不是普通的冒泡,也没有捕获阶段。

属性:

boolean altKey
number button
number buttons
number clientX
number clientY
boolean ctrlKey
boolean getModifierState(key)
boolean metaKey
number pageX
number pageY
DOMEventTarget relatedTarget
number screenX
number screenY
boolean shiftKey

Selection Events

事件名:

onSelect

Touch Events

事件名:

onTouchCancel onTouchEnd onTouchMove onTouchStart

属性:

boolean altKey
DOMTouchList changedTouches
boolean ctrlKey
boolean getModifierState(key)
boolean metaKey
boolean shiftKey
DOMTouchList targetTouches
DOMTouchList touches

UI Events

事件名:

onScroll

属性:

number detail
DOMAbstractView view

Wheel Events

事件名:

onWheel

属性:

number deltaMode
number deltaX
number deltaY
number deltaZ

Media Events

事件名:

onAbort onCanPlay onCanPlayThrough onDurationChange onEmptied onEncrypted 
onEnded onError onLoadedData onLoadedMetadata onLoadStart onPause onPlay 
onPlaying onProgress onRateChange onSeeked onSeeking onStalled onSuspend 
onTimeUpdate onVolumeChange onWaiting

Image Events

事件名:

onLoad onError

Animation Events

事件名:

onAnimationStart onAnimationEnd onAnimationIteration

属性:

string animationName
string pseudoElement
float elapsedTime

Transition Events

事件名:

onTransitionEnd

属性:

string propertyName
string pseudoElement
float elapsedTime

Other Events

事件名:

onToggle

对比算法

render函数将会比对两个虚拟DOM,并高效更新真实DOM。

  1. 每当根元素有不同类型,React将卸载旧树并重新构建新树
  2. 当比较两个相同类型的React DOM元素时,React则会观察二者的属性,保持相同的底层DOM节点,并仅更新变化的属性
  3. 当组件更新时,实例仍保持一致,以让状态能够在渲染之间保留

优化

diff算法,仅同层比较,有三种操作:新增、移动、删除。

兄弟元素强烈推荐使用key属性以提高更新效率。

API

React

类方法:

React.createElement(type, [props], [...children]),建议用JSX代替。
React.createFactory(type),过时不推荐使用。
React.cloneElement(element, [props], [...children]),以 element 作为起点,克隆并返回一个新的React元素(React Element)。
React.isValidElement(object),验证对象是否是一个React元素。

1. React.Component

React组件的基类。

类属性:

defaultProps,被定义为组件类的一个属性,用以为类设置默认的属性
displayName,被用在调试信息中

实例属性:

props,包含了组件该调用者定义的属性。
state,状态是该组件的特定数据,其可能改变多次。状态由用户定义,且其应为纯JavaScript对象。

实例方法:
setState(updater, [callback])

更新状态,并通知组件及其子组件需要用更新的状态来重新渲染。
不是立刻更新组件。其可能是批处理或推迟更新。

updater可以是一个函数((prevState, props)=>{}),也可以是一个对象。

forceUpdate(callback)

调用forceUpdate()将会导致组件的 render()方法被调用,并忽略shouldComponentUpdate()。

2. React.PureComponent

React.PureComponent 与 React.Component 几乎完全相同,但 React.PureComponent 通过prop和state的浅对比来实现 shouldComponentUpate()

3. React.Children

React.Children 提供了处理 this.props.children 这个不透明数据结构的工具

React.Children.map(children, function[(thisArg)])
React.Children.forEach(children, function[(thisArg)])
React.Children.count(children)
React.Children.only(children)
React.Children.toArray(children)

4. React.Fragment

<React.Fragment></React.Fragment>可以简写为<></>

5. React.forwardRef

高阶函数不可以传递ref,但是可以通过React.forwardRef来解决。

需要传入React.forwardRef一个函数——入参为props和ref

ReactDOM

ReactDOM.render(element, container, [callback])

  1. 渲染一个React元素,添加到位于提供的container里的DOM元素中,并返回这个组件的一个 引用。
  2. 如果这个React元素之前已经被渲染到container里去了,这段代码就会进行一次更新,并且只会改变那些反映元素最新状态所必须的DOM元素。
  3. 回调函数是可选的。如果你提供了,程序会在渲染或更新之后执行这个函数。

ReactDOM.unmountComponentAtNode(container)

  1. 从DOM元素中移除已挂载的React组件,清除它的事件处理器和state。
  2. 有组件被卸载的时候返回true,没有组件可供卸载时返回 false。

ReactDOM.findDOMNode(component)

  1. 如果这个组件已经被挂载到DOM中,函数会返回对应的浏览器中生成的DOM元素 。
  2. 可以通过ref来避免使用这个函数

ReactDOMServer

ReactDOMServer 类可以让你在服务端渲染你的组件。

ReactDOMServer.renderToString(element)

把一个React元素渲染为原始的HTML。

ReactDOMServer.renderToStaticMarkup(element)

类似 renderToString,但是不会创建额外的DOM属性。

参考

React 官方文档
React 中文文档
关于react diff 算法(译文)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions