资讯专栏INFORMATION COLUMN

理解JSX

W4n9Hu1 / 2746人阅读

摘要:原本是有自己的来负责的解析,不过现在已经停止更新,语法完全依赖进行解析。关于上面的几个转码的结果的解释都在下面的源码中这里可以发现,支持,但是比如就一定会报错了,虽然看起来与一样

首先jsx绝不是一个新的语言,我觉得他仅仅是js的超集,或者只是一种语法糖。原本FB是有自己的jsx-transform来负责jsx的解析,不过现在已经停止更新,jsx语法完全依赖babel进行解析。

babel

babel在识别jsx的时候,会将标签直接作为AST的node,然后转化

class Square extends React.Component {
  render() {
    return (
      
    );
  }
}

将被babel转化为

class Square extends React.Component {
  render() {
    return React.createElement(
      "button",
      { className: "square" },
      this.props.value
    );
  }
}

这里为了方便和阅读对es6的转化,暂时忽略。

AST

还是针对上面的代码,来看一下babylon AST的解析结果,只包含return部分
整个标签部分是JSXElement
其中会有三个部分openingElement,closingElement和children,属性则会成为openingElement的JSXAttribute

jsx在babel的定义

defineType("JSXElement", {
  builder: ["openingElement", "closingElement", "children", "selfClosing"],
  visitor: ["openingElement", "children", "closingElement"],
  aliases: ["JSX", "Immutable", "Expression"],
  fields: {
    openingElement: {
      validate: assertNodeType("JSXOpeningElement"),
    },
    closingElement: {
      optional: true,
      validate: assertNodeType("JSXClosingElement"),
    },
    children: {
      validate: chain(
        assertValueType("array"),
        assertEach(
          assertNodeType(
            "JSXText",
            "JSXExpressionContainer",
            "JSXSpreadChild",
            "JSXElement",
            "JSXFragment",
          ),
        ),
      ),
    },
  },
});

AST的jsx节点最后会被替换为createElement的形式,也就是说不管怎么用jsx,其实也就只是一种语法糖,与createElement的写法无异

e.g

为了更好的理解jsx,那我解释一段最近看到的代码

methodsParamsList.map((ListSourceComponent, index) => {
       return 
})

核心也就是openingElement

在babel的眼里他做为Element有两个部分,名字和属性,属性不多说了。
ListSourceComponent.component会被认为是JSXMemberExpression,ListSourceComponent是JSXIdentifier的对象component则是属性
如果是

那么ListSourceComponent是JSXIdentifier的name

整个代码的结果也就是

 methodsParamsList.map((ListSourceComponent, index) => {
      return React.createElement(ListSourceComponent.component, { index: index + 1 });
    });

其实在转码的阶段是否将JSXMemberExpression的name或者对象的首字母大写是不重要的,真的导致报错的也不过是在createElement中

createElement
createElement()

React.createElement(type, [props],[...children])

Create and return a new React element of the given type. The type argument can be either a tag name string (such as "div" or "span"), or a React component type (a class or a function).
Code written with JSX will be converted to use React.createElement(). You will not typically invoke React.createElement() directly if you are using JSX. See React Without JSX to learn more.

reactComponent大写的原因

在刚学react的时候,老师就说过react component需要大写,react会把大写开口的作为react的组件,不然则会使普通的html dom,比如div,span
首先是不是在解析ast的时候就把大小写分开处理了,答案是否定的,在定义openingElement的type的时候完全没有对这个进行判断,不管是大写,小写均作为string,是element的type
但是在babel的结果里可以看到
React.createElement("div", ...)
React.createElement( Div, ...)
这两种结果带来的就是Div这个是一个字符串还是变量名,如果自己不慎写了个小写的component名,那么一个并不是html标签的字符串必然会造成错误
这里必须穿插一个JSX dot notation

JSX dot notation

这个和上面的例子相关就是dot notation在jsx中的解析

methodsParamsList.map((ListSourceComponent, index) => {
       return 
    })
methodsParamsList.map((listSourceComponent, index) => {
       return 
    })

上面两段代码都不会导致错误,原因就是在解析JSXIdentifier的结果会是一组对象和属性,所以转码结果一定不是字符串而是obj.pro

jsx的变形

上面说到了在构建ast的过程中大小写并不进行区分,而是在@babel/plugin-transform-react-jsx中进行变化。
关于上面的几个转码的结果的解释都在下面的源码中

  const createIdentifierParser = (id: string) => () => {
    return id
      .split(".")
      .map(name => t.identifier(name))
      .reduce((object, property) => t.memberExpression(object, property));
  };

这里可以发现,react支持dot notation,但是比如

就一定会报错了,虽然看起来与

一样

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/93556.html

相关文章

  • 精益 React 学习指南 (Lean React)- 1.2 JSX 语法

    摘要:需要提醒读者的是,的很多例子都是通过来写的,但这并不是语法,后面我们会有单独的一小节讲解的基本语法,不过目前为止我们先将跟多精力放在上。 书籍完整目录 1.2 JSX 语法 showImg(https://segmentfault.com/img/bVvKLR); 官方文档 https://facebook.github.io/react/docs/jsx-in-depth.html ...

    moven_j 评论0 收藏0
  • 虚拟DOM内部是如何工作的

    摘要:但是它与里大部分的概率是保持一致的。但是如何将转换成函数的调用呢就是干这件事情的。好了,让我们看看是如何工作的。下面的图片在流程图中高亮了一个组件是如何工作的最后希望这篇文章能帮助你理解是如何工作的至少在中 英文原文链接 Virtual DOM很神奇,同时也比较复杂,难以理解。react,preact和相似的js库都使用了virtual dom。然而,我找不到任何好的文章或者文档,可以...

    hiYoHoo 评论0 收藏0
  • React.js学习笔记之JSX解读

    摘要:学习笔记之解读前端技术不多说,大腿很粗什么是是的核心组成部分,它使用标记的方式去直接声明界面,界面组件之间可以互相嵌套。它的目的是通过各种编译器将这些标记编译成标准的语言。的标签与函数名都是使用的驼峰命名。目前,一个的,只能返回一个节点。 React.js学习笔记之JSX解读 @(前端技术) Why React? 不多说,Facebook大腿很粗 什么是JSX JSX是React的核心...

    tianlai 评论0 收藏0
  • React.js 小书 Lesson7 - 组件的 render 方法

    摘要:一个组件类必须要实现一个方法,这个方法必须要返回一个元素。你也可以把它改成,它就会显示小书。注意,直接使用在的元素上添加类名如这种方式是不合法的。现在页面上是显示小书。下一节中我们将介绍小书组件的组合嵌套和组件树。 React.js 小书 Lesson7 - 组件的 render 方法 本文作者:胡子大哈本文原文:http://huziketang.com/books/react/l...

    Near_Li 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<