【问题标题】:JSX: when are JavaScript expressions evaluated?JSX:何时评估 JavaScript 表达式?
【发布时间】:2019-01-29 04:43:47
【问题描述】:

在阅读了 GatsbyJS 和 React 教程后,我得到的印象是 JavaScript 表达式总是在 JSX 中的 {} 括号内进行计算。但现在我正在查看 GatsbyJS 初始存储库中的 JSX 文件,看起来括号会导致不同的行为:

const {
    data: {
      posts: { edges: posts },
      site: {
        siteMetadata: { facebook }
      }
    }
} = props;

(Source)

根据教程,“facebook”应该被评估为 JavaScript 并且应该返回 undefined,但这不是正在发生的事情。不知何故,我们最终得到了一个 JavaScript 对象 data.site.siteMetadata.facebook,其中包含一些数据。这里发生了什么?为什么“facebook”不被评估为 JavaScript 表达式?

【问题讨论】:

标签: javascript reactjs jsx gatsby


【解决方案1】:

您复制的那段代码实际上与 JSX 无关(见下文)。它是 ES6 object destructuring syntax,就像 @PrithvirajSahu 对这个问题发表的评论一样。

假设你有一个这样的对象:

const obj = {
  a: 100, 
  b: { 
    value: 200,
  } 
};

您可以像这样获取内部值:

const { a } = obj; 
// same as const a = obj.a

const { b: c } = obj; 
// same as const c = obj.b

const { b: { value } } = obj; 
// same as const value = obj.b.value

const { b: { value: v } } = obj; 
// same as const v = obj.b.value

const { a, { b: { value } } } = obj; 
// same as 
// const a = obj.a; 
// const value = obj.b.value;

所以回到你的那段代码,它相当于

const posts = props.data.posts.edges;
const facebook = props.data.site.siteMetadata.facebook;

正如您所发现的,解构语法在 1 级或 2 级时非常简洁,但当有更多时很难阅读。就个人而言,我只在 1 级使用它。


编辑:在源码中的函数中,只有<...开头的行是JSX语法。

const CategoryPage = props => {
  // code here is normal js
  const { ... } = props;

  // JSX start from inside this return function
  return (
    <React.Fragment>
      { /* code between bracket in this section will be evaluate as 'normal JS' */ }
    </React.Fragment>
  )
}

警告:JSX 中括号之间的代码必须计算为函数。如果我们这样写:

<div className="container">
  Hello
  {"Happy"}
  World
</div>

Babel 会将其变成如下常规 JS:

React.createElement(
  "div",
  { className: "container" },
  "Hello",
  "Happy",
  "World"
);

Play with babel here

我们放在括号之间的任何内容都将作为div 元素的子元素传递给React.createElement;因此这里只能放置有效的 React 元素:

  • 空(不渲染)
  • 字符串(将成为 DOM 文本节点)
  • 另一个 React 元素
  • 一个表达式/函数,计算结果或返回上述任何一个
<div>
  { hasDate && <Date /> }
<div>

// somewhere in the code
const showDate = (hasDate) => {
  if (!hasDate) return null;
  return <Date />
}

// in the render function
return (
  <div>
    { showDate(hasDate) }
  <div>
)

我们也可以使用方括号将值传递给元素的 props:

<div 
  style={ { color: 'red' } }
  onClick={ (event) => {...} }>
  { hasDate && <Date /> }
<div>

【讨论】:

  • 你是对的。 Minor nitpick:你说代码与 JSX 无关。确实如此。它在一个 JSX 文件中,我的问题是为什么它没有被评估为 JavaScript,尽管有括号。
  • 嘿@AtteJuvonen,我已经编辑了上面的答案以澄清。当一个文件被命名为.jsx 时,它通常向你的编译器表明文件的内容将具有 JSX 语法——这并不意味着文件中的所有内容都是 JSX。在您分享的函数中,只有 &lt;...&gt; 部分是 JSX 语法。 { } 是一种逃避 JSX 的方法,因此您可以输入普通的 JS 代码。但是其他任何地方都是普通的JS。如果你把这个解构代码放在.jsx 之外并放到一个普通的ES6 .js 文件中,它会起作用。
  • 嘿,非常感谢。还有一件事:看起来我无法将“普通 JS”放在那里。例如,如果我输入"if (true) { console.log("hey") }",它会抱怨语法错误。
  • 嘿@AtteJuvonen!我的错,它实际上不是 normal js 本身——让我再编辑一下答案。但简而言之,JSX 会被编译成React.createElement(),也就是说只能传入值或者函数;但不是文字代码块。如果您将该代码提取到一个函数中,然后在 jsx 中调用该函数,它将起作用
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-21
相关资源
最近更新 更多