react 新特性 2019

1. Time Slicing

时间分片

官方说明是可以进行异步的渲染,不会阻塞当前的线程,当cpu足够用的话,看起来是同步渲染的,当cpu很吃紧的时候,会看到有点卡顿,但不至于卡死,对于开发者透明,不影响开发过程。

原理暂时没搞明白,渲染的方式肯定还是同步的渲染下来,至少父子组件的渲染是同步,猜测是把渲染任务推到任务队列里,然后一个个去执行,如果主线程很忙就会执行频率降低,如果主线程不忙就执行频率和同步没区别。

 

2. Suspense , 与 lazy

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

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

使用React.lazy方法包裹传入组件的函数,

加载的过程中显示fallback传入的组件,加载完成后显示真正的组件

注意,Suspense可以包含多个懒加载的组件

这可以解决组件异步加载的问题,如果OthoerComponent组件很庞大,庞大到需要1秒时间来加载,那么如果不用lazy的话,MyComponent的执行必须等OthoerComponent加载完才能执行,但是现在我们可以先渲染MyComponent再去加载OtherComponent,加载完后把loading组件替换成OtherComponnet

 

3. React.memo

纯函数组件没有shouldComponentUpdate()这样的钩子,每当父组件render,纯函数组件就会重新render一次,即使纯函数组件的参数没有变化。为了给这个纯函数组件检查参数是否变化了,就必须写成一个Class,在她shouldComponentUpdate()里检查Props,

React.memo就是为了帮我们方便得处理这样的问题而不用去写一个class,

import React from "react";

function Child({seconds}){
    console.log('I am rendering');
    return (
        <div>I am update every {seconds} seconds</div>
    )
};

function areEqual(prevProps, nextProps) {
    if(prevProps.seconds===nextProps.seconds){
        return true
    }else {
        return false
    }

}
export default React.memo(Child,areEqual)

React.memo()可接受2个参数,第一个参数为纯函数的组件,第二个参数用于对比props控制是否刷新,与shouldComponentUpdate()功能类似

又可以偷懒了,其实这样的函数自己实现也容易,相当于把第一参数作为render,第二个参数作为shouldComponentUpdate去创建一个组件,具体react的实现应该会比我们自己实现的性能更好

4. React.Profiler 性能分析

React 16.5 添加了对新的 profiler DevTools 插件的支持。这个插件使用 React 的 Profiler 实验性 API 去收集所有 component 的渲染时间,目的是为了找出你的 React App 的性能瓶颈。它将会和我们即将发布的 时间片 特性完全兼容。

这个工具以后有机会再看,大概是个能够检查渲染性能工具

 

5.

Hooks

解决 class 中生命周期函数经常包含不相关的逻辑,但又把相关逻辑分离到了几个不同方法中的问题

如果一个组件需要监听窗口的变换来调整自己,那么他就需要在mounted时增加监听,在willUnmount时移除监听,这样的代码是没问题,在在逻辑上并不合理,如果能把增加监听和移除监听写到一块就比较清晰了。

import React, { useState } from 'react';

function Example() {
	const [count, setCount] = useState(0);
	  // 声明多个 state 变量
  const [age, setAge] = useState(42);
  const [fruit, setFruit] = useState('banana');
  const [todos, setTodos] = useState([{ text: '学习 Hook' }]);
 
    return (
      <div>
        <p>You clicked {count} times</p>
        <button onClick={() => setCount(count + 1)}>
        Click me
       </button>
     </div>
   );
  }

我理解hook实际上是这么工作,render时使用useState从一个状态池中取出一个状态,并且提供一个函数可以修改这个状态,这个状态池和这个render函数绑定,也就是说每个状态池都属于这个render函数,状态池实际上是个空数组,并且有个游标也和这个函数绑定,每当函数开始执行,游标置为0,当调用一次useState后,游标加一,useState会去这个状态池的游标对应的位置去获取元素,如果这个函数是第一次执行则会将useState的参数先存到油标对应的状态池里。按这个思路,我打算有时间自己实现一个hook来玩玩。

另一个点,useEffect

function FriendStatus(props) {
  const [isOnline, setIsOnline] = useState(null);

  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }

    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    // Specify how to clean up after this effect:
    return function cleanup() {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });

  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}
componentDidMount,componentUpdate时执行 useEffect里的函数

useEffect传入一个函数,在首次执行render函数时会将userEffect传入的函数保存起来,存在render函数下,在组件挂载,更新时执行传入的函数,在组件卸载时调用返回的函数(cleanup),如果组件频繁更新则会导致频繁地执行副作用。并且这将非render的任务写到了render里,个人觉得虽然代码骚起来了,但代码也更乱了,更难维护了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值