Vue到React文中只纪录最关键,最突出的形象化差别

lxf2023-02-16 15:49:39

序言

  • 从技术栈Vue变为React是比较常见的状况,文中就得环节做一个归纳纪录。
  • 立即学习培训React的小白开发人员也可以作为参照。
  • 文中里面的内容多数为本人遇到的难题或是思索。这当中绝大多数官方网站都是有表明。

Vue到React

文中只纪录最关键,最突出的形象化差别。如果你想要详尽的功能对比,建议大家看本文。

  • 假如你用过Vue的3D渲染函数公式和JSX,这个知识点和React是相近的。但在React中这一部分比例比较重。由于Vue大部分时候建议使用模版词法。但注意仅仅类似,JSX编译程序可能并不一样。细分化查询官方网站这儿。
  • React不容易全自动替你更新视图,部件内部结构数据信息变更后,必须手动式setState。假如传到子组件的props产生变化,子组件会开启再次3D渲染。
  • React里的props比Vue更加灵活。基本上可以看做是Vue的props slot。

疑难问题

引起无限循环

1. 部件上直接启用会开启re-render的思路

export const MyComponent = (props) => {
  const [t, setT] = useState(0);
  // 每一次部件3D渲染都是会再次走到这里,setState又再次开启部件3D渲染
  setT((o) => o   1);
  return <h1>{t}</h1>;
};

2. useEffect无依靠时启用re-render的思路(和1相近)

export const MyComponent = (props) => {
  const [t, setT] = useState(0);
  // 由于无依靠,部件每一次3D渲染进行之后进到useEffect的调整,setState又再次开启部件3D渲染
  useEffect(() => {
    setT((o) => o   1);
  });
  return <h1>{t}</h1>;
};

3. 不正确设定props初始值

这一点是最隐敝,最容易忽略的,一定要十分谨慎。

export const MyComponent = (props) => {
  // arr是一个引用类型,引用类型给予初始值,每一次3D渲染时都赋了一个不一样地址引入。
  const { arr = [] } = props;
  const [t, setT] = useState(0);
  // useEffet会以为props arr出现了改变,因为每次3D渲染都是会进到调整,事实上和状况2一样了
  useEffect(() => {
    setT((o) => o   1);
  }, [arr]);
  return <h1>{t}</h1>;
};

函数中取过的值未升级

1. setState异步更新

export const MyComponent = (props) => {
  const [t, setT] = useState(0);
  useEffect(() => {
    setT((o) => o   1);
    // setState后立刻同歩获得,获得过的为升级前值
    console.log(t, 't'); // 0
  }, []);
  return <h1>{t}</h1>;
};

2. Hooks闭包圈套

针对setState异步更新里的事例,再去拓展一下,不难发现useState的闭包难题。

export const MyComponent = (props) => {
  const [t, setT] = useState(0);
  useEffect(() => {
    setT((o) => o   1);
    // 毕竟是时钟频率难题,就强制推迟实行state获得实际操作,就会发现仍然取不上系统重装后的state
    setTimeout(() => {
      console.log(t, 't0'); // 0
    }, 1000);
  }, []);
  return <h1>{t}</h1>;
};
  • 形成原因:简单讲,事例里的effect会在初次3D渲染完了强制执行,effect函数在实施时建立自已的执行上下文,自变量t由于闭包的主要原因一直存在该执行上下文中,当第二次3D渲染,t升级了,事实上和effect里的t在内存中是两个自变量。若是在依靠页面上添加t,useEffect内部结构会自动升级自变量t。

3. 解决方案

难题1、2的具体缘故和优化解决方案,可参考本文。这儿得出本人常用解决方法

  • 在useEffect中,假如逻辑性容许,能把自变量参与到依靠页面上。例如针对以上事例,假如你只要获得t,而且打印出,就可将其参与到依靠目录。而例子中既要get,还得set。假如参与到依靠目录会引起无限循环
  • 应用useRef。useRef建立的自变量根植于部件全部生命期。所以不用担心闭包难题。

容易忽略这个概念

这一部分是自己在细读官方网站后,发觉与我以前了解存有偏差一些定义。

useEffect的消除机会

  1. 实行下一个 effect 以前,上一个 effect 就已经被消除。即useEffect的调整强制执行前,消除上一次的调整。
export const MyComponent = (props) => {
  const [t, setT] = useState(0);
  useEffect(() => {
    if (t < 5) {
      setT((o) => o   1);
    }
    // 在return的函数中实行消除的思路
    return () => {
      console.log(t); //打印出了5次,0 1 2 3 4
    };
  });
  return <h1 onClick={() => {}}>{t}</h1>;
};
  1. 部件卸载掉时一定会启用一次消除。这也就是为什么可以使用依靠为空数组的useEffect取代部件卸载掉的生命周期

JSX针对不同算法设计的处理方式

  • 布尔类型、Null 及其 Undefined 可能忽视
// 能够放心大胆写如下所示分辨编码,不用担心true或是undefined被3D渲染到页面中。但要谨慎0和NaN
{t && <h1>{t}</h1>}
  • 二维数组能被结构3D渲染,即按序3D渲染二维数组里的每一项

动态组件

如果某个环境下的部件必须动态性3D渲染,能够有两种计划方案。

  • 先把部件名取值给一个大写的自变量,务必英文大写,然后使用JSX3D渲染。这儿展现官网事例
import React from 'react';
import { PhotoStory, VideoStory } from './stories';

const components = {
  photo: PhotoStory,
  video: VideoStory
};

function Story(props) {
  // 恰当!JSX 种类能是英文大写字母开头自变量。const SpecificStory = components[props.storyType];
  return <SpecificStory story={props.story} />;
}
  • 直接用createElement方式建立部件,此方法的第一个主要参数可以用正常自变量。因此更新改造官方网站事例。
import React, { createElement } from 'react';
import { PhotoStory, VideoStory } from './stories';

const components = {
  photo: PhotoStory,
  video: VideoStory
};

function Story(props) {
  // c为js自变量就可以
  const c = components[props.storyType];
  return createElement(c, { story: props.story });
}