潜台词:为什么React要用JSX?而不是用别的什么呢?
回答思路:通过 比较论证 的方式证明用 JSX 更胜一筹。
考察:

  1. 技术广度,深挖知识面涉及广度,对流行框架的模板方案是否知悉了解;
  2. 技术方案调研能力;

回答技巧:
三步走技巧:即 “一句话解释,核心概念,方案对比”的解题思路,来回答面试中“为什么 React 使用 JSX?”这类问题。

  1. 一句话解释 JSX。首先能一句话说清楚 JSX 到底是什么。
  2. 核心概念。JSX 用于解决什么问题?如何使用?
  3. 方案对比。与其他的方案对比,说明 React 选用 JSX 的必要性。

    一句话解释 JSX

    官方解释:JSX 是一个 JS 的语法扩展,或说是一个类似于 XML 的 ECMAScript 语法扩展。(本身没有太多语法定义,也不期望引入更多标准)

    核心概念

    React 不强制要求使用 JSX。若没有 JSX 时,React 实现一个组件依赖于使用React.createElement函数 。
    JSX 更像是 语法糖,通过类似 XML 的描述方式,描述函数对象。
    用 JSX 和不用 JSX 对比: ```typescript // 不用 JSX class Hello extends React.Component { render() {
    1. return React.createElement(
    2. 'div',
    3. null,
    4. `Hello ${this.props.toWhat}`
    5. );
    } } ReactDOM.render( React.createElement(Hello, {toWhat: ‘World’}, null), document.getElementById(‘root’) );

// 用 JSX class Hello extends React.Component { render() { return

Hello {this.props.toWhat}
; } } ReactDOM.render( , document.getElementById(‘root’) );

  1. 对比发现:用 JSX 后,代码简洁,代码结构层次分明。<br />React 需将组件转化为虚拟 DOM 树,所以编写的代码,实际上是手写一颗结构树。而 XML 在树结构的描述上天生具有可读性强的优势。<br />Babel 插件将 JSX 语法转换为 `React.createELement`代码。
  2. <a name="xf5KI"></a>
  3. ## 方案对比
  4. <a name="S04CD"></a>
  5. ### 模板
  6. 引入了太多的概念,如:模板语法、模板指令等。<br />JSX 代码更加简洁,可读性好,更贴近 HTML
  7. <a name="iTwLa"></a>
  8. ### 模板字符串
  9. 结构嵌套过深时,代码结构变得更加复杂,代码提示也变得困难。
  10. <a name="jdav8"></a>
  11. ### JXON
  12. 最终放弃 JXON 这一方案的原因是,大括号不能为元素在树中开始和结束的位置,提供很好的语法提示。
  13. <a name="Lmm8Y"></a>
  14. ## 答题
  15. JSX 是一个 JS 的语法扩展,结构类似 XML。<br />JSX 主要用于声明 React 元素,但 React 中并不强制使用 JSX。即使使用了 JSX,也会在构建过程中,通过 Babel 插件编译为 React.createElement。所以 JSX 更像是 React.createElement 的一种语法糖。<br />React 团队并不想引入 JavaScript 本身以外的开发体系。而是希望通过合理的关注点分离保持组件开发的纯粹性。<br />JSX 以外的三种技术方案进行对比。<br />首先是模板,React 团队认为模板不应该是开发过程中的关注点,因为引入了模板语法、模板指令等概念,是一种不佳的实现方案。<br />其次是模板字符串,模板字符串编写的结构会造成多次内部嵌套,使整个结构变得复杂,并且优化代码提示也会变得困难重重。<br />最后是 JXON,同样因为代码提示困难的原因而被放弃。<br />所以 React 最后选用了 JSX,因为 JSX 与其设计思想贴合,不需要引入过多新的概念,对编辑器的代码提示也极为友好。<br />![](https://cdn.nlark.com/yuque/0/2022/jpeg/12647972/1653862391522-03011cf4-7f40-40f6-85c4-4f9acc62addc.jpeg)
  16. <a name="SJQNV"></a>
  17. ## 进阶
  18. **Babel 插件如何实现 JSX JS 的编译?** React 面试中,这个问题很容易被追问,也经常被要求手写。<br />原理:Babel 读取代码并解析,生成 AST,再将 AST 传入插件层进行转换,在转换时就可以将 JSX 的结构转换为 React.createElement 的函数。如下代码所示:
  19. ```typescript
  20. module.exports = function (babel) {
  21. var t = babel.types;
  22. return {
  23. name: "custom-jsx-plugin",
  24. visitor: {
  25. JSXElement(path) {
  26. var openingElement = path.node.openingElement;
  27. var tagName = openingElement.name.name;
  28. var args = [];
  29. args.push(t.stringLiteral(tagName));
  30. var attribs = t.nullLiteral();
  31. args.push(attribs);
  32. var reactIdentifier = t.identifier("React"); //object
  33. var createElementIdentifier = t.identifier("createElement");
  34. var callee = t.memberExpression(reactIdentifier, createElementIdentifier)
  35. var callExpression = t.callExpression(callee, args);
  36. callExpression.arguments = callExpression.arguments.concat(path.node.children);
  37. path.replaceWith(callExpression, path.node);
  38. },
  39. },
  40. };
  41. };

TODO:弄清楚这段代码是如何运行起来的???
查询 Babel 的开发文档