react版本:16.13.1

1.React 顶层 API

React.Component

React.Component 是使用 ES6 classes 方式定义 React 组件的基类

React.PureComponent

React.PureComponent 与 React.Component 很相似。两者的区别在于 React.Component 并未实现 shouldComponentUpdate(),而 React.PureComponent 中以浅层对比 prop 和 state 的方式来实现了该函数。

React.memo

const MyComponent = React.memo(function MyComponent(props) {
  /* 使用 props 渲染 */
});

React.memo 为高阶组件。它与 React.PureComponent 非常相似,但只适用于函数组件,而不适用 class 组件。
React.memo 仅检查 props 变更。如果函数组件被 React.memo 包裹,且其实现中拥有 useState 或 useContext 的 Hook,当 context 发生变化时,它仍会重新渲染。

如果你想要控制对比过程,那么请将自定义的比较函数通过第二个参数传入来实现。

function MyComponent(props) {
  /* 使用 props 渲染 */
}
function areEqual(prevProps, nextProps) {
  /*
  如果把 nextProps 传入 render 方法的返回结果与
  将 prevProps 传入 render 方法的返回结果一致则返回 true,
  否则返回 false
  */
}
export default React.memo(MyComponent, areEqual);

与 class 组件中 shouldComponentUpdate() 方法不同的是,如果 props 相等,areEqual 会返回 true;如果 props 不相等,则返回 false。这与 shouldComponentUpdate 方法的返回值相反。

createElement()

React.createElement(
  type,
  [props],
  [...children]
)

创建并返回指定类型的新 React 元素

cloneElement()

React.cloneElement(
  element,
  [props],
  [...children]
)

以 element 元素为样板克隆并返回新的 React 元素。返回元素的 props 是将新的 props 与原始元素的 props 浅层合并后的结果。新的子元素将取代现有的子元素,而来自原始元素的 key 和 ref 将被保留。

createFactory()

返回用于生成指定类型 React 元素的函数。此辅助函数已废弃,建议使用 JSX 或直接调用 React.createElement() 来替代它

React.createFactory(type)

isValidElement()

React.isValidElement(object)

验证对象是否为 React 元素,返回值为 true 或 false。


const Hello = <h1>Hello </h1>;
const App = () => <div>{Hello}</div>;
console.log('Hello is valid? ', isValidElement(Hello)); 
// => true
console.log('App is valid? ',  isValidElement(App)); 
// => false

React.Children

React.Children 提供了用于处理 this.props.children 不透明数据结构的实用方法。

React.Children.map
React.Children.map(children, function[(thisArg)])

在 children 里的每个直接子节点上调用一个函数,并将 this 设置为 thisArg。如果 children 是一个数组,它将被遍历并为数组中的每个子节点调用该函数。如果子节点为 null 或是 undefined,则此方法将返回 null 或是 undefined,而不会返回数组。

如果 children 是一个 Fragment 对象,它将被视为单一子节点的情况处理,而不会被遍历。

React.Children.forEach
React.Children.forEach(children, function[(thisArg)])

与 React.Children.map() 类似,但它不会返回一个数组。

React.Children.count
React.Children.count(children)

返回 children 中的组件总数量,等同于通过 map 或 forEach 调用回调函数的次数。

React.Children.only
React.Children.only(children)

验证 children 是否只有一个子节点(一个 React 元素),如果有则返回它,否则此方法会抛出错误。

React.Children.toArray
React.Children.toArray(children)

将 children 这个复杂的数据结构以数组的方式扁平展开并返回,并为每个子节点分配一个 key

React.Fragment

React.Fragment 组件能够在不额外创建 DOM 元素的情况下,让 render() 方法中返回多个元素。

render() {
  return (
    <React.Fragment>
      Some text.
      <h2>A heading</h2>
    </React.Fragment>
  );
}

你也可以使用其简写语法 <></>

React.createRef

React.createRef 创建一个能够通过 ref 属性附加到 React 元素的 ref。

class MyComponent extends React.Component {
  constructor(props) {
    super(props);

    this.inputRef = React.createRef();
  }

  render() {
    return <input type="text" ref={this.inputRef} />;
  }

  componentDidMount() {
    this.inputRef.current.focus();
  }
}

React.forwardRef

React.forwardRef 会创建一个React组件,这个组件能够将其接受的 ref 属性转发到其组件树下的另一个组件中

const FancyButton = React.forwardRef((props, ref) => (
  <button ref={ref} className="FancyButton">
    {props.children}
  </button>
));

// You can now get a ref directly to the DOM button:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;

当 React 附加了 ref 属性之后,ref.current 将直接指向 DOM 元素实例

React.lazy

React.lazy() 允许你定义一个动态加载的组件。这有助于缩减 bundle 的体积,并延迟加载在初次渲染时未用到的组件。

使用 React.lazy 的动态引入特性需要 JS 环境支持 Promise。在 IE11 及以下版本的浏览器中需要通过引入 polyfill 来使用该特性。

// 这个组件是动态加载的
const SomeComponent = React.lazy(() => import('./SomeComponent'));

React.Suspense

React.Suspense 可以指定加载指示器(loading indicator),以防其组件树中的某些子组件尚未具备渲染条件。目前,懒加载组件是 <React.Suspense> 支持的唯一用例

// 该组件是动态加载的
const OtherComponent = React.lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    // 显示 <Spinner> 组件直至 OtherComponent 加载完成
    <React.Suspense fallback={<Spinner />}>
      <div>
        <OtherComponent />
      </div>
    </React.Suspense>
  );
}

2.React.Component

组件的生命周期

挂载

当组件实例被创建并插入 DOM 中时,其生命周期调用顺序如下:

  • constructor()
  • static getDerivedStateFromProps()
  • render()
  • componentDidMount()
更新

当组件的 props 或 state 发生变化时会触发更新。组件更新的生命周期调用顺序如下:

  • static getDerivedStateFromProps()
  • shouldComponentUpdate()
  • render()
  • getSnapshotBeforeUpdate()
  • componentDidUpdate()
卸载

当组件从 DOM 中移除时会调用如下方法:

  • componentWillUnmount()
错误处理

当渲染过程,生命周期,或子组件的构造函数中抛出错误时,会调用如下方法:

  • static getDerivedStateFromError()
  • componentDidCatch()

生命周期图谱
在这里插入图片描述
在这里插入图片描述

render()

render() 方法是 class 组件中唯一必须实现的方法。

当 render 被调用时,它会检查 this.props 和 this.state 的变化并返回以下类型之一:

  • React 元素。通常通过 JSX 创建。无论是
    还是 均为 React 元素
  • 数组或 fragments。
  • Portals
  • 字符串或数值类型。它们在 DOM 中会被渲染为文本节点
  • 布尔类型或 null。什么都不渲染

constructor()

如果不初始化 state 或不进行方法绑定,则不需要为 React 组件实现构造函数。

在 React 中,构造函数仅用于以下两种情况:

  • 通过给 this.state 赋值对象来初始化内部 state。
  • 为事件处理函数绑定实例
constructor(props) {
  super(props);
  // 不要在这里调用 this.setState()
  this.state = { counter: 0 };
  this.handleClick = this.handleClick.bind(this);
}

componentDidMount()

componentDidMount() 会在组件挂载后(插入 DOM 树中)立即调用。依赖于 DOM 节点的初始化应该放在这里。如需通过网络请求获取数据,此处是实例化请求的好地方。

你可以在 componentDidMount() 里直接调用 setState()。它将触发额外渲染,但此渲染会发生在浏览器更新屏幕之前。如此保证了即使在 render() 两次调用的情况下,用户也不会看到中间状态。

componentDidUpdate()

componentDidUpdate(prevProps, prevState, snapshot)

componentDidUpdate() 会在更新后会被立即调用。首次渲染不会执行此方法。

当组件更新后,可以在此处对 DOM 进行操作。

你也可以在 componentDidUpdate() 中直接调用 setState(),但请注意它必须被包裹在一个条件语句里,正如上述的例子那样进行处理,否则会导致死循环。它还会导致额外的重新渲染,虽然用户不可见,但会影响组件性能。

如果组件实现了 getSnapshotBeforeUpdate() 生命周期(不常用),则它的返回值将作为 componentDidUpdate() 的第三个参数 “snapshot” 参数传递。否则此参数将为 undefined。

如果 shouldComponentUpdate() 返回值为 false,则不会调用 componentDidUpdate()。

componentWillUnmount()

componentWillUnmount() 会在组件卸载及销毁之前直接调用。在此方法中执行必要的清理操作。

componentWillUnmount() 中不应调用 setState(),因为该组件将永远不会重新渲染。组件实例卸载后,将永远不会再挂载它。

shouldComponentUpdate()

shouldComponentUpdate(nextProps, nextState)

当 props 或 state 发生变化时,shouldComponentUpdate() 会在渲染执行之前被调用。返回值默认为 true。首次渲染或使用 forceUpdate() 时不会调用该方法。
PureComponent 会对 props 和 state 进行浅层比较,并减少了跳过必要更新的可能性。

请注意,返回 false 并不会阻止子组件在 state 更改时重新渲染。
如果 shouldComponentUpdate() 返回 false,则不会调用 UNSAFE_componentWillUpdate(),render() 和 componentDidUpdate()

static getDerivedStateFromProps()

static getDerivedStateFromProps(props, state)

getDerivedStateFromProps 会在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。它应返回一个对象来更新 state,如果返回 null 则不更新任何内容。此方法无权访问组件实例。

请注意,不管原因是什么,都会在每次渲染前触发此方法。这与 UNSAFE_componentWillReceiveProps 形成对比,后者仅在父组件重新渲染时触发,而不是在内部调用 setState 时。

getSnapshotBeforeUpdate()

getSnapshotBeforeUpdate(prevProps, prevState)

getSnapshotBeforeUpdate() 在最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息。此生命周期的任何返回值将作为参数传递给 componentDidUpdate()。

static getDerivedStateFromError()

static getDerivedStateFromError(error)

此生命周期会在后代组件抛出错误后被调用。 它将抛出的错误作为参数,并返回一个值以更新 state

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    // 更新 state 使下一次渲染可以显降级 UI
    return { hasError: true };
  }

  render() {
    if (this.state.hasError) {
      // 你可以渲染任何自定义的降级  UI
      return <h1>Something went wrong.</h1>;
    }

    return this.props.children; 
  }
}

componentDidCatch()

componentDidCatch(error, info)
//error —— 抛出的错误。
//info —— 带有 componentStack key 的对象,其中包含有关组件引发错误的栈信息。

此生命周期在后代组件抛出错误后被调用。
componentDidCatch() 会在“提交”阶段(render后)被调用,因此允许执行副作用。

过时的生命周期方法

UNSAFE_componentWillMount()

此生命周期之前名为 componentWillMount。该名称将继续使用至 React 17。

UNSAFE_componentWillMount() 在挂载之前被调用。它在 render() 之前调用,因此在此方法中同步调用 setState() 不会触发额外渲染。

此方法是服务端渲染唯一会调用的生命周期函数。

UNSAFE_componentWillReceiveProps()
UNSAFE_componentWillReceiveProps(nextProps)

此生命周期之前名为 componentWillReceiveProps。该名称将继续使用至 React 17。
UNSAFE_componentWillReceiveProps() 会在已挂载的组件接收新的 props 之前被调用。

在挂载过程中,React 不会针对初始 props 调用 UNSAFE_componentWillReceiveProps()。组件只会在组件的 props 更新时调用此方法。调用 this.setState() 通常不会触发 UNSAFE_componentWillReceiveProps()。

UNSAFE_componentWillUpdate()
UNSAFE_componentWillUpdate(nextProps, nextState)

此生命周期之前名为 componentWillUpdate。该名称将继续使用至 React 17。

当组件收到新的 props 或 state 时,会在渲染之前调用 UNSAFE_componentWillUpdate()。使用此作为在更新发生之前执行准备更新的机会。初始渲染不会调用此方法。

注意,你不能此方法中调用 this.setState();在 UNSAFE_componentWillUpdate() 返回之前,你也不应该执行任何其他操作(例如,dispatch Redux 的 action)触发对 React 组件的更新

如果你在此方法中读取 DOM 信息,则可以将此逻辑移至 getSnapshotBeforeUpdate() 中。

如果 shouldComponentUpdate() 返回 false,则不会调用 UNSAFE_componentWillUpdate()。

setState()

setState(updater, [callback])

setState() 将对组件 state 的更改排入队列,并通知 React 需要使用更新后的 state 重新渲染此组件及其子组件。

setState() 并不总是立即更新组件。它会批量推迟更新。这使得在调用 setState() 后立即读取 this.state 成为了隐患。为了消除隐患,请使用 componentDidUpdate 或者 setState 的回调函数(setState(updater, callback))

除非 shouldComponentUpdate() 返回 false,否则 setState() 将始终执行重新渲染操作。

参数一为带有形式参数的 updater 函数:

this.setState((state, props) => {
  return {counter: state.counter + props.step};
});

state 是对应用变化时组件状态的引用。updater 的返回值会与 state 进行浅合并
setState() 的第一个参数除了接受函数外,还可以接受对象类型:

this.setState({quantity: 2})

会将传入的对象浅层合并到新的 state 中。
setState() 的第二个参数为可选的回调函数,它将在 setState 完成合并并重新渲染组件后执行。通常,我们建议使用 componentDidUpdate() 来代替此方式。

forceUpdate()

component.forceUpdate(callback)

默认情况下,当组件的 state 或 props 发生变化时,组件将重新渲染。如果 render() 方法依赖于其他数据,则可以调用 forceUpdate() 强制让组件重新渲染。

调用 forceUpdate() 将致使组件调用 render() 方法,此操作会跳过该组件的 shouldComponentUpdate()。但其子组件会触发正常的生命周期方法,包括 shouldComponentUpdate() 方法。

defaultProps

defaultProps 可以为 Class 组件添加默认 props。

class CustomButton extends React.Component {
  // ...
}

CustomButton.defaultProps = {
  color: 'blue'
};

displayName

displayName 字符串多用于调试消息。通常,你不需要设置它,因为它可以根据函数组件或 class 组件的名称推断出来。

3. ReactDOM

react-dom 的 package 提供了可在应用顶层使用的 DOM(DOM-specific)方法

React 支持所有的现代浏览器,包括 IE9 及以上版本,但是需要为旧版浏览器比如 IE9 和 IE10 引入相关的 polyfills 依赖。

render()

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

在提供的 container 里渲染一个 React 元素,并返回对该组件的引用(或者针对无状态组件返回 null)。

如果提供了可选的回调函数,该回调将在组件被渲染或更新之后被执行。

hydrate()

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

与 render() 相同,但它用于在 ReactDOMServer 渲染的容器中对 HTML 的内容进行 hydrate 操作。React 会尝试在已有标记上绑定事件监听器。

unmountComponentAtNode()

ReactDOM.unmountComponentAtNode(container)

从 DOM 中卸载组件,会将其事件处理器(event handlers)和 state 一并清除。如果指定容器上没有对应已挂载的组件,这个函数什么也不会做。如果组件被移除将会返回 true,如果没有组件可被移除将会返回 false。

findDOMNode()

ReactDOM.findDOMNode(component)

React.findDOMNode(this.refs.myTextInput).focus();

如果组件已经被挂载到 DOM 上,此方法会返回浏览器中相应的原生 DOM 元素。大多数情况下,你可以绑定一个 ref 到 DOM 节点上,可以完全避免使用 findDOMNode。

当组件渲染的内容为 null 或 false 时,findDOMNode 也会返回 null。当组件渲染的是字符串时,findDOMNode 返回的是字符串对应的 DOM 节点。从 React 16 开始,组件可能会返回有多个子节点的 fragment,在这种情况下,findDOMNode 会返回第一个非空子节点对应的 DOM 节点。

findDOMNode 不能用于函数组件。

createPortal()

ReactDOM.createPortal(child, container)

创建 portal。Portal 将提供一种将子节点渲染到 DOM 节点中的方式,该节点存在于 DOM 组件的层次结构之外。

4. ReactDOMServer

ReactDOMServer 对象允许你将组件渲染成静态标记。通常,它被使用在 Node 服务端上:

// ES modules
import ReactDOMServer from 'react-dom/server';
// CommonJS
var ReactDOMServer = require('react-dom/server');

概览

下述方法可以被使用在服务端和浏览器环境。

  • renderToString()
  • renderToStaticMarkup()

下述附加方法依赖一个只能在服务端使用的 package(stream)。它们在浏览器中不起作用。

  • renderToNodeStream()
  • renderToStaticNodeStream()

renderToString()

ReactDOMServer.renderToString(element)

将 React 元素渲染为初始 HTML。React 将返回一个 HTML 字符串。你可以使用此方法在服务端生成 HTML,并在首次请求时将标记下发,以加快页面加载速度,并允许搜索引擎爬取你的页面以达到 SEO 优化的目的。

如果你在已有服务端渲染标记的节点上调用 ReactDOM.hydrate() 方法,React 将会保留该节点且只进行事件处理绑定,从而让你有一个非常高性能的首次加载体验。

renderToStaticMarkup()

ReactDOMServer.renderToStaticMarkup(element)

此方法与 renderToString 相似,但此方法不会在 React 内部创建的额外 DOM 属性

renderToNodeStream()

ReactDOMServer.renderToNodeStream(element)

将一个 React 元素渲染成其初始 HTML。返回一个可输出 HTML 字符串的可读流。通过可读流输出的 HTML 完全等同于 ReactDOMServer.renderToString 返回的 HTML。

renderToStaticNodeStream()

ReactDOMServer.renderToStaticNodeStream(element)

此方法与 renderToNodeStream 相似,但此方法不会在 React 内部创建的额外 DOM 属性。
通过可读流输出的 HTML,完全等同于 ReactDOMServer.renderToStaticMarkup 返回的 HTML。

5. DOM 元素

React 实现了一套独立于浏览器的 DOM 系统,兼顾了性能和跨浏览器的兼容性。我们借此机会完善了浏览器 DOM 实现的一些特殊情况。

在 React 中,所有的 DOM 特性和属性(包括事件处理)都应该是小驼峰命名的方式。

dangerouslySetInnerHTML

dangerouslySetInnerHTML 是 React 为浏览器 DOM 提供 innerHTML 的替换方案。通常来讲,使用代码直接设置 HTML 存在风险,因为很容易无意中使用户暴露于跨站脚本(XSS)的攻击。因此,你可以直接在 React 中设置 HTML,但当你想设置 dangerouslySetInnerHTML 时,需要向其传递包含 key 为 __html 的对象,以此来警示你。例如:

function createMarkup() {
  return {__html: 'First &middot; Second'};
}

function MyComponent() {
  return <div dangerouslySetInnerHTML={createMarkup()} />;
}

htmlFor

由于 for 在 JavaScript 中是保留字,所以 React 元素中使用了 htmlFor 来代替。

onChange

人们可能习惯于使用onInput文本输入和文本区域,因为对于原始DOM,在控件失去焦点之前,这些控件的onChange事件不会触发。最后,我们有两个事件- onInput和onChange-的工作方式相同。

style

style 接受一个采用小驼峰命名属性的 JavaScript 对象,而不是 CSS 字符串。这与 DOM 中 style 的 JavaScript 属性是一致的,同时会更高效的,且能预防跨站脚本(XSS)的安全漏洞。
React 会自动添加 ”px” 后缀到内联样式为数字的属性后。

value

<input> 和 <textarea> 组件支持 value 属性。你可以使用它为组件设置 value。这对于构建受控组件是非常有帮助。defaultValue 属性对应的是非受控组件的属性,用于设置组件第一次挂载时的 value。如果存在value,则defaultValue改变input框的值不会改变,还是value的值。

6. 合成事件

获取event对象

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>

上面两个例子中,参数 e 作为 React 事件对象将会被作为第二个参数进行传递。通过箭头函数的方式,事件对象必须显式的进行传递,但是通过 bind 的方式,事件对象以及更多的参数将会被隐式的进行传递。

事件池

SyntheticEvent 是合并而来。这意味着 SyntheticEvent 对象可能会被重用,而且在事件回调函数被调用后,所有的属性都会无效。出于性能考虑,你不能通过异步访问事件。

function onClick(event) {
  console.log(event); // => nullified object.
  console.log(event.type); // => "click"
  const eventType = event.type; // => "click"

  setTimeout(function() {
    console.log(event.type); // => null
    console.log(eventType); // => "click"
  }, 0);

  // 不起作用,this.state.clickEvent 的值将会只包含 null
  this.setState({clickEvent: event});

  // 你仍然可以导出事件属性
  this.setState({eventType: event.type});
}

如果你想异步访问事件属性,你需在事件上调用 event.persist(),此方法会从池中移除合成事件,允许用户代码保留对事件的引用。

支持的事件

以下的事件处理函数在冒泡阶段被触发。如需注册捕获阶段的事件处理函数,则应为事件名添加 Capture。例如,处理捕获阶段的点击事件请使用 onClickCapture,而不是 onClick。

Clipboard Events
Composition Events
Keyboard Events
Focus Events
Form Events
Generic Events
Mouse Events
Pointer Events
Selection Events
Touch Events
UI Events
Wheel Events
Media Events
Image Events
Animation Events
Transition Events
Other Events

剪贴板事件

事件名:
onCopy onCut onPaste
属性:
DOMDataTransfer clipboardData

复合事件

事件名:
onCompositionEnd onCompositionStart onCompositionUpdate
属性:
string data

键盘事件

事件名:
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

焦点事件

事件名:
onFocus onBlur
这些焦点事件在 React DOM 上的所有元素都有效,不只是表单元素。
属性:
DOMEventTarget relatedTarget

表单事件

事件名:
onChange onInput onInvalid onReset onSubmit

通用事件

事件名称:
onError onLoad

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

指针事件

事件名:
onPointerDown onPointerMove onPointerUp onPointerCancel onGotPointerCapture
onLostPointerCapture onPointerEnter onPointerLeave onPointerOver onPointerOut
onPointerEnter 和 onPointerLeave 事件从离开的元素向进入的元素传播,不是正常的冒泡,也没有捕获阶段。

属性:
number pointerId
number width
number height
number pressure
number tangentialPressure
number tiltX
number tiltY
number twist
string pointerType
boolean isPrimary

选择事件

事件名:
onSelect

触摸事件

事件名:
onTouchCancel onTouchEnd onTouchMove onTouchStart
属性:
boolean altKey
DOMTouchList changedTouches
boolean ctrlKey
boolean getModifierState(key)
boolean metaKey
boolean shiftKey
DOMTouchList targetTouches
DOMTouchList touches

UI 事件

事件名:
onScroll
属性:
number detail
DOMAbstractView view

滚轮事件

事件名:
onWheel
属性:
number deltaMode
number deltaX
number deltaY
number deltaZ

媒体事件

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

图像事件

事件名:
onLoad onError

动画事件

事件名:
onAnimationStart onAnimationEnd onAnimationIteration
属性:
string animationName
string pseudoElement
float elapsedTime

过渡事件

事件名:
onTransitionEnd
属性:
string propertyName
string pseudoElement
float elapsedTime

其他事件

事件名:
onToggle

7. Test Utilities

import ReactTestUtils from 'react-dom/test-utils'; // ES6
var ReactTestUtils = require('react-dom/test-utils'); // ES5 使用 npm 的方式

概览

ReactTestUtils 可搭配你所选的测试框架,轻松实现 React 组件测试。在 Facebook 内部,我们使用 Jest 来轻松实现 JavaScript 测试。

API

act()
mockComponent()
isElement()
isElementOfType()
isDOMComponent()
isCompositeComponent()
isCompositeComponentWithType()
findAllInRenderedTree()
scryRenderedDOMComponentsWithClass()
findRenderedDOMComponentWithClass()
scryRenderedDOMComponentsWithTag()
findRenderedDOMComponentWithTag()
scryRenderedComponentsWithType()
findRenderedComponentWithType()
renderIntoDocument()
Simulate

选择

测试框架选择:https://loveky.github.io/2018/04/02/write-unit-test-for-react-part1-choose-test-framwork/
推荐使用:Jest+Enzyme
Jest官网: https://jestjs.io/zh-Hans/
enzyme文档:https://enzymejs.github.io/enzyme/

8. Test Renderer

import TestRenderer from 'react-test-renderer'; // ES6
const TestRenderer = require('react-test-renderer'); // ES5 with npm

概览

这个 package 提供了一个 React 渲染器,用于将 React 组件渲染成纯 JavaScript 对象,无需依赖 DOM 或原生移动环境。

这个 package 提供的主要功能是在不依赖浏览器或 jsdom 的情况下,返回某个时间点由 React DOM 或者 React Native 平台渲染出的视图结构(类似与 DOM 树)快照。

API

TestRenderer

TestRenderer.create()
TestRenderer.act()

TestRenderer instance

testRenderer.toJSON()
testRenderer.toTree()
testRenderer.update()
testRenderer.unmount()
testRenderer.getInstance()
testRenderer.root

TestInstance

testInstance.find()
testInstance.findByType()
testInstance.findByProps()
testInstance.findAll()
testInstance.findAllByType()
testInstance.findAllByProps()
testInstance.instance
testInstance.type
testInstance.props
testInstance.parent
testInstance.children

例子

你可以使用 Jest 的快照测试功能来自动保存当前 JSON 树结构到一个文件中,并在测试中检查它是否被修改

import TestRenderer from 'react-test-renderer';

function Link(props) {
  return <a href={props.page}>{props.children}</a>;
}

const testRenderer = TestRenderer.create(
  <Link page="https://www.facebook.com/">Facebook</Link>
);

console.log(testRenderer.toJSON());
// { type: 'a',
//   props: { href: 'https://www.facebook.com/' },
//   children: [ 'Facebook' ] }

你也可以通过遍历输出来查找特定节点,并对它们进行断言。

import TestRenderer from 'react-test-renderer';

function MyComponent() {
  return (
    <div>
      <SubComponent foo="bar" />
      <p className="my">Hello</p>
    </div>
  )
}

function SubComponent() {
  return (
    <p className="sub">Sub</p>
  );
}

const testRenderer = TestRenderer.create(<MyComponent />);
const testInstance = testRenderer.root;

expect(testInstance.findByType(SubComponent).props.foo).toBe('bar');
expect(testInstance.findByProps({className: "sub"}).children).toEqual(['Sub']);

9. JavaScript 环境要求

React 16 依赖集合类型 Map 和 Set 。如果你要支持无法原生提供这些能力(例如 IE < 11)或实现不规范(例如 IE 11)的旧浏览器与设备,考虑在你的应用库中包含一个全局的 polyfill ,例如 core-jsbabel-polyfill

React 16 使用 core-js 支持老版本浏览器,其 polyfill 环境可能如下:

import 'core-js/es/map';
import 'core-js/es/set';

import React from 'react';
import ReactDOM from 'react-dom';

ReactDOM.render(
  <h1>Hello, world!</h1>,
  document.getElementById('root')
);

React 同时还依赖于 requestAnimationFrame(甚至包括测试环境)。 你可以使用 raf 的 package 增添 requestAnimationFrame 的 shim:

import 'raf/polyfill';

兼容ie8用react还是vue?

兼容ie8建议使用react,因为vue不兼容ie8,Vue.js使用了IE8不能模拟的ECMAScript 5特性。

React 术语词汇表

元素

React 元素是构成 React 应用的基础砖块。人们可能会把元素与广为人知的“组件”概念相互混淆。元素描述了你在屏幕上想看到的内容。React 元素是不可变对象。

const element = <h1>Hello, world</h1>;

通常我们不会直接使用元素,而是从组件中返回元素。

组件

React 组件是可复用的小的代码片段,它们返回要在页面中渲染的 React 元素。React 组件的最简版本是,一个返回 React 元素的普通 JavaScript 函数:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

props

props 是 React 组件的输入。它们是从父组件向下传递给子组件的数据。

记住,props 是只读的。不应以任何方式修改它们.

state 和 props 之间最重要的区别是:props 由父组件传入,而 state 由组件本身管理。组件不能修改 props,但它可以修改 state。

props.children

每个组件都可以获取到 props.children。它包含组件的开始标签和结束标签之间的内容。

受控组件 vs 非受控组件

React 有两种不同的方式来处理表单输入。

如果一个 input 表单元素的值是由 React 控制,就其称为受控组件。

一个非受控组件,就像是运行在 React 体系之外的表单元素。当用户将数据输入到表单字段(例如 input,dropdown 等)时,React 不需要做任何事情就可以映射更新后的信息。然而,这也意味着,你无法强制给这个表单字段设置一个特定值。

在大多数情况下,你应该使用受控组件。

key

“key” 是在创建元素数组时,需要用到的一个特殊字符串属性。key 帮助 React 识别出被修改、添加或删除的 item。应当给数组内的每个元素都设定 key,以使元素具有固定身份标识。

Ref

React 支持一个特殊的、可以附加到任何组件上的 ref 属性。此属性可以是一个由 React.createRef() 函数创建的对象、或者一个回调函数、或者一个字符串(遗留 API)。当 ref 属性是一个回调函数时,此函数会(根据元素的类型)接收底层 DOM 元素或 class 实例作为其参数。这能够让你直接访问 DOM 元素或组件实例。

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐