react的高级特性

高级特性

代码分割

import

使用import进行代码分割, 异步加载

//使用之前
import { add } from './math';
console.log(add(16, 26));

//使用之后
import("./math").then(math => {
  console.log(math.add(16, 26));
});

react.lazy

//使用之前
import OtherComponent from './OtherComponent';

//使用之后
const OtherComponent = React.lazy(() => import('./OtherComponent'));

React.lazy 接受一个函数,这个函数需要动态调用 import()。它必须返回一个 Promise,该 Promise 需要 resolve 一个 default export 的 React 组件。

然后应在 Suspense 组件中渲染 lazy 组件,如此使得我们可以使用在等待加载 lazy 组件时做优雅降级(如 loading 指示器等)。

import React, { Suspense } from 'react';

const OtherComponent = React.lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <OtherComponent />
      </Suspense>
    </div>
  );
}

fallback 属性接受任何在组件加载过程中你想展示的 React 元素。你可以将 Suspense 组件置于懒加载组件之上的任何位置。你甚至可以用一个 Suspense 组件包裹多个懒加载组件。

fragment

Fragments 允许你将子列表分组,而无需向 DOM 添加额外节点。

render() {
  return (
    <React.Fragment>
      <ChildA />
      <ChildB />
      <ChildC />
    </React.Fragment>
  );
}
//等同于 空标签
render() {
  return (
    <>
      <ChildA />
      <ChildB />
      <ChildC />
    </>
  );
}

显示的 Fragments 支持传递key属性, 其他属性与事件暂时不支持

函数组件

非受控组件

在大多数情况下,我们推荐使用 受控组件 来处理表单数据。在一个受控组件中,表单数据是由 React 组件来管理的。另一种替代方案是使用非受控组件,这时表单数据将交由 DOM 节点来处理。

要编写一个非受控组件,而不是为每个状态更新都编写数据处理函数,你可以 使用 ref 来从 DOM 节点中获取表单数据。

Portals

Portal 提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优秀的方案。

ReactDOM.createPortal(child, container)

第一个参数(child)是任何可渲染的 React 子元素,例如一个元素,字符串或 fragment。第二个参数(container)是一个 DOM 元素。

render() {
  // React 并*没有*创建一个新的 div。它只是把子元素渲染到 `domNode` 中。
  // `domNode` 是一个可以在任何位置的有效 DOM 节点。
  return ReactDOM.createPortal(
    this.props.children,
    domNode
  );
}

render props

术语 “render prop” 是指一种在 React 组件之间使用一个值为函数的 prop 共享代码的简单技术

具有 render prop 的组件接受一个函数,该函数返回一个 React 元素并调用它而不是实现自己的渲染逻辑。

class Cat extends React.Component {
  render() {
    const mouse = this.props.mouse;
    return (
      <img src="/cat.jpg" style={{ position: 'absolute', left: mouse.x, top: mouse.y }} />
    );
  }
}

class Mouse extends React.Component {
  constructor(props) {
    super(props);
    this.handleMouseMove = this.handleMouseMove.bind(this);
    this.state = { x: 0, y: 0 };
  }

  handleMouseMove(event) {
    this.setState({
      x: event.clientX,
      y: event.clientY
    });
  }

  render() {
    return (
      <div style={{ height: '100vh' }} onMouseMove={this.handleMouseMove}>

        {/*
          Instead of providing a static representation of what <Mouse> renders,
          use the `render` prop to dynamically determine what to render.
        */}
        {this.props.render(this.state)}
      </div>
    );
  }
}

class MouseTracker extends React.Component {
  render() {
    return (
      <div>
        <h1>移动鼠标!</h1>
        <Mouse render={mouse => (
          <Cat mouse={mouse} />
        )}/>
      </div>
    );
  }
}

重要的是要记住,render prop 是因为模式才被称为 render prop ,你不一定要用名为 render 的 prop 来使用这种模式。事实上, 任何被用于告知组件需要渲染什么内容的函数 prop 在技术上都可以被称为 “render prop”.

尽管之前的例子使用了 render,我们也可以简单地使用 children prop!

<Mouse children={mouse => (
  <p>鼠标的位置是 {mouse.x},{mouse.y}</p>
)}/>

context

异步组件

//常见问题比如,常见的性能优化方案

  • import()
  • React.lazy
  • React.Suspense

性能优化

思考: 性能优化对于React更加重要?
思考: setState强调的不可变值

shouldComponentUpdate (SCU)

shouldComponentUpdate(nextProps,nextState){
    if(nextState.count !== this.state.count){
      return true //渲染
    }
    return false //不渲染
  }
  • react默认父组件更新, 子组件则无条件更新.
  • shouldComponentUpdate 默认返回true, 因此手动控制是否更新, 进行性能优化
  • SCU一定要每次都用吗? 需要的时候才优化

总结

  • SCU默认返回true, 即React默认重新渲染所有子组件
  • 必须配合"不可变值"一起使用
  • 可先不用SCU, 有性能问题时再考虑使用

PureComponent 和 React.memo

使用: class Demo extends React.PureComponent
效果: 默认使用SCU中的浅比较

React.Memo就是函数组件中的PureComponent

function Com(props){}

//写一个类似SCU的函数, 传进memo中
function areEqual(prevProps,nextProps){}

export default React.memo(Com,areEqual)

不可变值 immutable.js

  • 彻底拥抱 不可变值
  • 基于共享收据(不是深拷贝), 速度好

深拷贝性能差

  • 有一定的学习和迁移成本, 按需使用
const map1 = Immutable.Map({a:1,b:2})
const map2 = map1.set('b',50)
map1.get('b') //2
map2.get('b') //50

小结

  • shouldComponentUpdate
  • PureComponent 和 React.memo
  • 不可变值 immutable.js
  • 按需使用 & state层级
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值