【问题标题】:React.js & [...] (spread) syntaxReact.js 和 [...](扩展)语法
【发布时间】:2019-07-24 14:20:39
【问题描述】:

基于页面中的示例:https://redux.js.org/basics/usage-with-react

我们有以下物品:

const Todo = ({ onClick, completed, text }) => (
  <li
    onClick={onClick}
    style={{
      textDecoration: completed ? 'line-through' : 'none'
    }}
  >
    {text}
  </li>
)

Todo.propTypes = {
  onClick: PropTypes.func.isRequired,
  completed: PropTypes.bool.isRequired,
  text: PropTypes.string.isRequired
}

此外,我们还有:

const TodoList = ({ todos, onTodoClick }) => (
  <ul>
    {todos.map((todo, index) => (
      <Todo key={index} {...todo} onClick={() => onTodoClick(index)} />
    ))}
  </ul>
)

谁能告诉我上面代码中的 {...todo} 是什么?

我知道 ... 运算符是一种扩展语法,可以说是 [...todos, newTodoItem] (将新的待办事项连接到旧的待办事项列表)。 但是,在上面的示例中,todo item 不是一个数组,它似乎生成了一个对象。因此对我来说,看起来 {...todo} 等于 {todo}。

另外,组件上分配了什么样的属性?

【问题讨论】:

标签: javascript reactjs redux react-redux


【解决方案1】:
const obj = {a: 1, b: 2, c: 3};

&lt;MyComponent {...obj} /&gt; 与 &lt;MyComponent a={1} b={2} c={3} /&gt; 相同。所以你使用spread 运算符... 从对象或数组中取出元素。

在 React 之外,如果 const test={a: 1, b:2 },那么 const x = {test} //es6 feature 类似于 const x = {test: test}。所以这和const x = {test: {a: 1, b:2}}是一样的

其中,&lt;MyComponent {obj} /&gt; 在 React 中创建错误,因为在 MyComponent 内部,可用于访问传递的 obj 的道具名称是什么?空无一人。因此错误。

function MyComponent(props) {
 // What is props.? to access obj
}

所以,你使用一个有名字的道具,

<MyComponent x={obj} />

function MyComponent(props) {
 // props.x has obj
 // props.x = obj
 console.log(props.x);
 return <div />
}

但是,展开运算符会自动将带有对象键和值的道具名称作为对象的值,如本答案开头所示。

正如您在问题中所说,const newTodos = [...todos, newItem] 创建了一个新数组,其中旧的待办事项从todos 展开,并添加了一个额外的newItem。如果,您没有传播todos,它将创建newTodos = [[todo1, todo2],newItem]。

【讨论】:

    【解决方案2】:

    ... 也可用于传播对象而不仅仅是数组。例如,

    // Using rest syntax here
    let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 }; 
    x; // 1
    y; // 2
    z; // { a: 3, b: 4 }
    
    // Using spread here
    let n = { x, y, ...z };
    n; // { x: 1, y: 2, a: 3, b: 4 }
    

    在上述情况下,todos 是一个包含键 completed 和 text 的对象数组。而不是像这样手动传递道具 -

    const TodoList = ({ todos, onTodoClick }) => (
      <ul>
        {todos.map((todo, index) => (
          <Todo key={index} completed={todo.completed} text={todo.text} onClick={() => onTodoClick(index)} />
        ))}
      </ul>
    )
    

    我们使用扩展语法将键值对添加为道具。您可以将其视为语法糖。

    【讨论】:

    • {todo} 不会做同样的事情吗?
    • 没有。 {todo} 将todo 的值作为一个整体使用。展开采用对象(或数组)内部的单个值。当您执行 时,prop 也引用了 todo 引用的对象。
    • 我猜这就像将一个对象的所有属性传播到单个对象。例如,在您的示例中,...z 类似于 {a}、{b}。对吗?
    • @ekalyvio 真的没有理由去猜测——答案是告诉你的,它已经记录在案了 :)
    【解决方案3】:

    ...todo 用于将 props 传递给 Todo 组件。在 Todo proptypes 中,您可以看到有两个可变类型的 props。所以 ... 运算符将其传播(传递)到 Todo 组件的 props

    【讨论】:

      猜你喜欢
      • 2014-01-15
      • 2020-02-24
      • 1970-01-01
      • 1970-01-01
      • 2019-04-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多