React高级指南

高级指南

 1.深入JSX:

从本质上讲,JSX 只是为 React.createElement(component, props, ...children) 函数提供的语法糖。

因为 JSX 被编译为 React.createElement 的调用,所以 React 库必须在你 JSX 代码的作用域中。

import React from 'react'

用户定义组件必须以大写字母开头

当一个元素类型以小写字母开头,它表示引用一个类似于 <div> 或者 <span> 的内置组件,会给 React.createElement 方法传递 'div' 或者 'span' 字符串。以大写字母开头的类型,类似于 <Foo />,会被编译成 React.createElement(Foo) ,对应于自定义组件 或者在 JavaScript 文件中导入的组件。

JSX 类型不能是表达式

return <components[props.storyType] story={props.story/>; 错误

 const SpecificStory = components[props.storyType];  return <SpecificStory story={props.story} />; 正确

JavaScript 表达式作为 props(属性)

你可以传递任何一个用 {} 包裹的 JavaScript 表达式作为 props(属性)。

{1+2+3} 但是 {if(..)else... 和 for(..)} 不是表达式

果你没给 prop(属性) 传值,那么他默认为 true 。下面两个 JSX 表达式是等价的:

<MyTextBox autocomplete /> <MyTextBox autocomplete={true} />

属性扩展

如果你已经有一个 object 类型的 props,并且希望在 JSX 中传入,你可以使用扩展操作符 ... 传入整个 props 对象。这两个组件是等效的:

function App1() { return <Greeting firstName="Ben" lastName="Hector" />; } function App2() { const props = {firstName: 'Ben', lastName: 'Hector'};  return <Greeting {...props} />; }


JSX会删除每行开头和结尾的空格,并且也会删除空行。邻接标签的空行也会被移除,字符串之间的空格会被压缩成一个空格,因此下面的渲染效果都是相同的:

JavaScript 表达式作为 Children(子元素)

通过使用 {} 包裹,你可以将任何的 JavaScript 元素而作为 children(子元素) 传递

Booleans, Null, 和 Undefined 被忽略

在有条件性渲染 React 元素时非常有用。如果 showHeader 为 true 时,<Header />会被渲染:

<div>
 {showHeader && <Header />} <Content /> </div>

需要注意的是“falsy”值,例如数值 0 ,仍然会被 React 渲染。例如,这段代码不会按照你预期的发生,因为当 props.messages 是一个空数组时 0 会被打印:

<div>
 {props.messages.length && <MessageList messages={props.messages} /> } </div> 

要修复这个问题,确保 && 之前的表达式总是布尔值:

<div>
 {props.messages.length > 0 && <MessageList messages={props.messages} /> }

2.使用 PropTypes 进行类型检查

 

3.静态类型检查

 

4.Refs 和 DOM

在常规的 React 数据流中,props 是父组件与子组件交互的唯一方式。要修改子元素,你需要用新的 props 去重新渲染子元素。然而,在少数情况下,你需要在常规数据流外强制修改子元素。被修改的子元素可以是 React 组件实例,或者是一个 DOM 元素。在这种情况下,React 提供了解决办法。

何时使用 Refs

下面有一些正好使用 refs 的场景:

  • 处理focus、文本选择或者媒体播放
  • 触发强制动画
  • 集成第三方DOM库

如果可以通过声明式实现,就尽量避免使用 refs 。

在 DOM 元素上添加 Ref

为 类(Class) 组件添加 Ref

Refs 与 函数式组件

 

5.不受控组件

在大多数情况下,我们推荐使用受控组件来实现表单。在受控组件中,表单数据由 React 组件负责处理。另外一个选择是不受控组件,其表单数据由 DOM 元素本身处理。

要编写一个未控制组件,你可以使用一个 ref 来从 DOM 获得 表单值,而不是为每个状态更新编写一个事件处理程序。

默认值

在 React 渲染生命周期中,表单元素中的 value 属性将会覆盖 DOM 中的 value 。在不受控组件中,你可能希望 React 有初始值,但保留后续更新不受控制。在这种情况下,你需要使用 defaultValue 属性而不是 value 属性。

同样, <input type="checkbox"> 和 <input type="radio"> 支持 defaultChecked,而 <select> 和 <textarea> 支持 defaultValue

6.优化性能

使用生产版本而不是使用开发版本

避免重新渲染

React 构建并维护渲染 UI 的内部表示。它包括你从组件中返回的 React 元素。这些内部状态使得 React 只有在必要的情况下才会创建DOM节点和访问存在DOM节点,因为对 JavaScript 对象的操作是比 DOM 操作更快。这被称为”虚拟DOM”,React Native 也是基于上述原理。

当组件的 props 和 state 改变时,React 通过比较新返回的元素 和 之前渲染的元素 来决定是否有必要更新DOM元素。当二者不相等时,则更新 DOM 元素。

如果你知道在某些情况下你的组件不需要更新,那么你可以在 shouldComponentUpdate返回 false 来跳过整个渲染过程,包括在这个组件和后面调用的 render() 。

在大多数情况下,您可以不用手写 shouldComponentUpdate() ,而是从 React.PureComponent 继承。 这相当于用当前和以前 props(属性) 和 state(状态) 的浅层比较来实现shouldComponentUpdate() 。

应用 shouldComponentUpdate

如果你想要你的组件仅当 props.color 或 state.count 发生改变时需要更新,你可以通过 shouldComponentUpdate 函数来检查:

class CounterButton extends React.Component { constructor(props) { super(props); this.state = {count: 1}; } shouldComponentUpdate(nextProps, nextState) { if (this.props.color !== nextProps.color) { return true; } if (this.state.count !== nextState.count) { return true; } return false; } render() { return ( <button color={this.props.color} onClick={() => this.setState(state => ({count: state.count + 1}))}> Count: {this.state.count} </button> ); } }

在这种情况下,shouldComponentUpdate 函数仅仅检查 props.color 或者 state.count 是否发生改变。如果这些值没有发生变化,则组件不会进行更新。如果你的组件更复杂,你可以使用类似于对 props 和 state 的所有属性进行”浅比较”这种模式来决定组件是否需要更新。这种模式非常普遍,因此 React 提供了一个 helper 实现上面的逻辑:继承 React.PureComponent 。因此,下面的代码是一种更简单的方式实现了相同的功能:

class CounterButton extends React.PureComponent { constructor(props) { super(props); this.state = {count: 1}; } render() { return ( <button color={this.props.color} onClick={() => this.setState(state => ({count: state.count + 1}))}> Count: {this.state.count} </button> ); } } 

大多数情况下,你可以使用 React.PureComponent 而不是自己编写 shouldComponentUpdate 。但 React.PureComponent 仅会进项浅比较,因此如果 props 或者 state 可能会导致浅比较失败的情况下就不能使用 React.PureComponent 。

避免这类问题最简单的方法是不要突变(mutate) props 或 state 的值。例如,上述 handleClick 方法可以通过使用 concat 重写:

handleClick() {
  this.setState(prevState => ({ words: prevState.words.concat(['marklar']) })); }

 

猜你喜欢

转载自www.cnblogs.com/eret9616/p/8927053.html