重读 react 官网

341 阅读6分钟
  1. react 灵活在哪里?

    答: 1.首先是数据流,vue中直接用v-model绑定,更方便,但是没那么灵活,react中需要自己处理state,所以在处理state的时候有很多灵活空间。 2.组件定义方式,vue是由模版、js、css组成,需要用vue的全部语法糖来处理组件,react则可以由函数或者类的方式来定义,可以在写函数的时候处理任意值。 3.js、css扩展库,vue是内嵌的工具和过渡动画,封装好的,react则是三方的库,可以自行选择如何处理。

  2. 为什么 react 设计返回单根节点?

    答:React DOM 是一个虚拟的 DOM,当组件上的状态发生更改时,React会比较新的虚拟DOM和旧的虚拟DOM,计算出哪些部分需要更新。如果组件返回多个根节点,则React需要比较和更新这些根节点,这样会影响性能。为什么没有在算法内部添加包装节点,自动添加包装节点可能会导致样式何行为上的意外影响,并可能使Web开发人员想更改DOM结构以实现视觉上期望的布局。

  3. 组件的概念

    答:在React中,组件是一个可重用的代码块,组件用于渲染、管理和更新应用程序中的UI元素,它拥有自己的逻辑和外观。React 应用程序是由 组件 组成的,组件可以小到一个按钮,也可以大到整个页面。

    export default function Square() {  
        return <button className="square">X</button>;  
    }
    
  4. 状态维护

    答:每个组件都会拥有自己的 state,可以维护自己的状态,并且进行更新。其中哪些是 state 呢? 标记出那些不是的:

  • 随着时间推移 保持不变? 如此,便不是 state。
  • 通过 props 从父组件传递? 如此,便不是 state。
  • 是否可以基于已存在于组件中的 state 或者 props 进行计算? 如此,它肯定不是state!

首先,从 React 引入 useState

import { useState } from 'react';

现在你可以在你的组件中声明一个 state 变量

function MyButton() {

  const [count, setCount] = useState(0);

  // ...

你将从 useState 中获得两样东西:当前的 state(count),以及用于更新它的函数(setCount)。你可以给它们起任何名字,但按照惯例,需要像这样 [something, setSomething] 为它们命名。

  1. 为什么在 react 中,共享变量不推荐放到子组件维护?

    答:如果在子组件中维护状态,父组件需要“询问”每个子组件的状态。这会使代码难以理解、容易出现错误,并且难以重构。相反,最好的方法是将游戏的状态存储在父组件中而不是每个子组件中。父组件可以通过传递一个 props,这种方法可以使代码更易于理解和维护,更好地管理组件之间的关系,使代码更易于开发和维护,并促进组件之间的松耦合。

当涉及变量共享时,通常需要以状态提升的方式重构 react 组件:

 export default function MyApp() {  

     const [count, setCount] = useState(0);  

     function handleClick() {  
         setCount(count + 1);  
     }  

     return (  
         <div>  
             <h1>Counters that update separately</h1>  
             <MyButton />  
             <MyButton />  
         </div>  
      ); 
 }  
 function MyButton() {  

 // ... we're moving code from here ...  

 }
  1. 父子组件之间的传参方式有哪些?分别用于什么场景?

    答:第一种,通过props传参,调用 setSquares 函数将告知 React 组件状态已改变,并且使用该状态的组件及其子组件重新渲染。

    function Square({ value, onSquareClick }) { 
        return ( 
            <button className="square" onClick={onSquareClick}> 
                {value}  
            </button>  
        );  
    }
    
    export default function Board() {
      const [squares, setSquares] = useState(Array(9).fill(null));
      function handleClick(i) { 
          const nextSquares = squares.slice();  
          nextSquares[i] = "X";  
          setSquares(nextSquares);  
      }
      return (
        <>
          <div className="board-row">
          {/*注意:像<Square value={squares[0]} onSquareClick={handleClick(0)} />
          这样直接添加handleClick(0)是错的,因为它是一个立即执行函数,会立即执行,引起循环渲染。
          而定义一个箭头函数,相当于是将箭头函数当做一个参数传递给了onSquareClick。
           */}
            <Square value={squares[0]} onSquareClick={() => handleClick(0)} />
            //...
      );
    }
    
    
  2. react 有哪些 hooks ,分别对应 class 的哪些生命周期,如何映射?

    答:以 use 开头的函数被称为 HookuseState 是 React 提供的一个内置 Hook。你可以在 React API 参考 中找到其他内置的 Hook。Hook 比普通函数更为严格。你只能在你的组件(或其他 Hook)的 顶层 调用 Hook。如果你想在一个条件或循环中使用 useState,请提取一个新的组件并在组件内部使用它。

  3. 为什么要创建副本,不改变原数组?

    答:在使用了 slice() 来创建每个 move 后 squares 数组的新副本,并将其视为不可变的。这将允许你存储 squares 数组的每个过去版本,并在它们之间导航。你将把过去的 squares 数组存储在另一个名为 history 的数组中,并将其作为一个新的状态变量进行存储。如果改变原数组,则全部储存的都是最后更新的这个变量值。

    [
      // Before first move
      [null, null, null, null, null, null, null, null, null],
      // After first move
      [null, null, null, null, 'X', null, null, null, null],
      // After second move
      [null, null, null, null, 'X', null, null, null, 'O'],
      // ...
    ]
    
  4. map 时为什么需要 key 值?正常的元素为什么不需要key值?

    答:当你交换了 Alexa 和 Ben 的顺序,并在 Alexa 和 Ben 之间插入了 Claudia时,由于 React 是一个计算机程序,无法知道你的意图,它需要为每个列表项指定一个键属性来将每个列表项与其兄弟区分开来。使用数据库中的id作为key是非常合适的。

    通常最好不要使用索引作为 key 值,因为索引可能会随着列表的增加或减少而变化。这可能导致 React 误认为某些新元素与之前的某个元素是同一个元素,因为它们在索引上是相同的。因为正常的元素react会用index作为key值,增加减少后直接更新组件树。

    在构建动态列表时,强烈建议为每个列表项指定适当的 key。如果没有适当的 key,建议重新组织数据以便指定 key。key 不需要在全局上是唯一的,它们只需要在组件及其兄弟组件之间是唯一的即可。

8.React 数据流是显式展示的,不是双向数据绑定? 答:是的。与双向数据绑定相比,需要更多的输入。如果你尝试在上述的例子中输入或者勾选复选框,发现 React 忽视了你的输入。这点是有意为之的。通过 <input value={filterText} />,已经设置了 inputvalue 属性,使之恒等于从 FilterableProductTable 传递的 filterText state。只要 filterText state 不设置,(输入框的)输入就不会改变。当用户更改表单输入时,state 将更新以反映这些更改。state 由 FilterableProductTable 所拥有,所以只有它可以调用 setFilterTextsetInStockOnly。使 SearchBar 更新 FilterableProductTable 的 state。

<input
  type="text"
  value={filterText}
  placeholder="Search..."
  onChange={(e) => onFilterTextChange(e.target.value)} />

记得从父组件将方法传进去

function FilterableProductTable({ products }) {
  const [filterText, setFilterText] = useState('');
  const [inStockOnly, setInStockOnly] = useState(false);

  return (
    <div>
      <SearchBar
        filterText={filterText}
        inStockOnly={inStockOnly}
        onFilterTextChange={setFilterText}
        onInStockOnlyChange={setInStockOnly} />