【问题标题】:Why can you only use expressions in JSX, not statements?为什么在 JSX 中只能使用表达式,不能使用语句?
【发布时间】:2020-04-02 09:45:14
【问题描述】:

在继续之前,我应该提一下,是的,我已经阅读了关于“Use if statement in React JSX”及其在 SO 和其他地方的不同变体的问题和答案。

然而,这些帖子更多地是关于 如何 在不使用 JSX 语句的情况下解决问题。我想知道 为什么 语句在 JSX 中是不允许的,我找不到任何帖子。

我正在阅读名为“If-Else in JSX”的官方文档,给出的原因是,引用,

JSX 只是函数调用和对象构造的语法糖

他们继续对比以下两段代码,第一段有效,第二段无效:

这是有效的:

// This JSX: 
ReactDOM.render(<div id="msg">Hello World!</div>, mountNode);
// Is transformed to this JS: 
ReactDOM.render(React.createElement("div", {id:"msg"}, "Hello World!"), mountNode); 

这是无效的:

// This JSX:
<div id={if (condition) { 'msg' }}>Hello World!</div>

// Is transformed to this JS:
React.createElement("div", {id: if (condition) { 'msg' }}, "Hello World!");

我真的很想了解这一点。首先,在第二个示例中,我从未想过在 HTML 元素的 id 属性中编写 JavaScript。事实上,这是我第一次看到在 id 属性中使用的任何类型的代码。如果我要尝试编写一个 if 条件,我会在渲染返回表达式中用花括号来做,作为其他有效 JS 的天真模拟(如 map 或三元表达式)。

render() {
return (
  {if ...
}
)

我毫不怀疑,对于本文档的作者来说,这个稍微不正统的示例解释了他们的断言,即“JSX 只是函数调用和对象构造的语法糖”,但我不知道如何解释。

p>

【问题讨论】:

  • 您提供的代码在每个字母中都相同。
  • validnot valid 是一样的
  • 函数的参数(或对象文字的值,在你的情况下)必须是表达式。 ({ id: if (condition) { 'msg' }}) 是语法错误。
  • 哎呀抱歉剪错了。但是文档页面的链接可以看到确切的示例。
  • 这些例子告诉你为什么。如果你在 JSX 中有语句,它会被转换为函数调用和对象字面量有语法错误

标签: javascript reactjs


【解决方案1】:

让我们从概念上开始。语句与表达式的定义是什么?

语句做某事。表达式的计算结果是一个值。

JSX 旨在构建并从代码的一个片段传递到另一个片段,最终以 HTML 结尾。这个名字甚至暗示了这种“JavaScript 到 XML”的转换。

它的全部意义在于返回 HTML 节点的“值”。 JSX 允许使用表达式,因为它们可以帮助您确定值。

也许仔细研究一下三元表达式和 if/else 之间的区别会有所帮助。

如果/否则

if(isSaturday){
   wakeUpHour = 10;
}else{
   wakeUpHour = 7;
}

三元

wakeUpHour = isSaturday ? 10 : 7;

它们都完成了同样的事情,对吧?但在幕后,它们的运作方式不同。在英语中,if/else 可能是:

  1. 如果 'isSaturday' 的值是真值,则运行大括号内的代码
  2. 将数字 10 分配给“wakeUpHour”
  3. 否则,运行下一个花括号内的代码
  4. 将数字 7 分配给“wakeUpHour”

三元语句也有两部分:

  1. 如果 isSaturday 为真,则值为 10。否则为 7。
  2. 将此值分配给“wakeUpHour”

我们认为这些都是完成同样的事情。这里的关键是三元表达式本身只是一个值。这不是代码行。 用那个值做某事需要另一个部分,分配它。

在 JSX 中,我们不想分配东西。我们想要价值观。所以我们只取三元表达式(一个值),而不是赋值部分或任何其他代码语句。

最后,希望不会增加您的困惑,我要指出您可以在 JSX 中定义函数。

const myJSX = <button onClick={ () => { return 'hello'; } }>Say hello</button>

等等,什么?我以为我们无法执行代码行。它不是执行代码行,而是定义它们;它被渲染到:

var myJSX = React.createElement("button", {onClick: () => {
  return 'hello';
}}, "Say hello");

将其与尝试仅抛出 if/else 语句进行比较:

const myJSX = <span>{ if(true){ return 'hello'; } }</span>

将尝试呈现为:

var myJSX = React.createElement("span", null, if(true){ return 'hello' });

这不起作用,原因与您通常不能将未封装的代码块传递到函数的参数中的原因相同。

【讨论】:

  • 这不是一个函数 call,它是一个函数 definition - 也许使用一个不是子函数的例子,因为函数不是有效的子函数.另外我不认为单独的 Babel JSX 插件会从箭头函数切换到普通函数。
  • 不错,不错。我确实相信 babel 默认会转换箭头函数,但我可能是错的。
  • babeljs.io/docs/en/babel-plugin-transform-react-jsx 不会,我不认为,链中的其他人(例如 preset-env)可能会。
  • 你说得对,我也是通过 es2015 运行的。
  • 非常感谢!您让 JSX 帮助生成 HTML 节点的动机是非常棒的可视化!
【解决方案2】:

也许这与您的问题无关,但我已被重定向到这里,因为我的一个问题据说与您的问题重复。 如果你想做多行 JavaScript 代码,你可以用 IIFE 包装你的 JS 代码,例如:

  <b>
    {(() => {
      const a = [1, 2, 3].find((el) => el === 2)
      // as much code as you want ...
      // ...
      // ...
      console.log(a)
    })()}
  </b>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-03
    • 2020-11-01
    • 1970-01-01
    • 2014-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-15
    相关资源
    最近更新 更多