微信号:frontshow

介绍:InfoQ大前端技术社群:囊括前端、移动、Node全栈一线技术,紧跟业界发展步伐。

React中JSX的本质:不是模板引擎,而是语法糖

2018-06-27 17:56 王沛
作者|王沛
编辑|覃云

在 React 的开发中,会经常使用一种特殊的语法来描述 React 的组件,叫做 JSX,虽然它看上去像是一种模板语言,但是其实它是一种语法糖。

JSX 的特点是能够让开发者在 JavaScript 代码中直接写 HTML 的标记,这也是 React 推出时最受争议的一点,就是如何去把 UI 的描述放到代码中。

比如我们先来定义一个变量 const name = ' Nate Wang ',再定义一个 HTML 的

const element = <h1>Hello,{name}</h1>;

把变量显示出来,定一个 h1 的标记。

所以可以看到 element 使用了一个 HTML 标记来表示一个节点,之所以这样去写,是因为它的本质是在于动态创建了一个组件,而且用的是 JavaScript 的语法。

了解 DOM 的 API 的话,你会发现除了用 HTML 描述一个节点,还可以用 JavaScript 的 DOM API,比如说 Document.creatElement 的方式来创建一个原生的 DOM 节点。

对 React 来说也是一样,当我们要创建一个组件的时候,既可以用声明式的方式像 HTML 标记一样去声明一个组件,同样我们也可以用 JavaScript 语法,比如说 React.creatElement 来动态地创建一个组件。

上图是一个很简单的例子:创建一个 h1 的标记,给它一个标记的类型,h1 就是 Comment 的第一个参数标记的类型。第二个传给它的属性,右侧的代码中并没有,所以是 null,Hello 是他的 Children,name 也是他的 Children,从第三个参数开始,后面都是这个元素的子元素,所以创建一个 h1 这样的 Element,我们可以很清楚的看到上图中左和右哪一种更直观,所以说 JSX 的本质是:可以让你去一种更方便的方式动态的创建组件。

上图是一个稍微复杂的例子,CommentBox 是一个评论框组件,一个自定义的组件,这里面不仅用到了 DOM 原生组件,还用到了自定义的组件,每个组件还可能给他它传一些属性,有些组件有可能会有 Children。

上图的右侧代码中我们可以看到,用一个 React.creatElement ,产生 div,传给它一些属性 className,div 下面的所有子节点一共有三个,分别用 React.creatElement 来创建:h1、CommentList、CommentForm。

所以也可以说 JSX 就是让你以声明方式来描述了这个动态创建组建的一个过程。

这样的好处在于:开发者可以完全利用 JavaScript 本身的语法,而不是发明了一种模板语言。

在其他的框架或者是在传统的模式下,开发者通常要学习一门模板语言来描述 UI 的变量,或者格式化的函数如何调用等等,但 JSX 并不是一个模板语言,它就是换了一种写法的 JavaScript,让开发者可以利用 JavaScript 本身的特性来做动态创建 UI 的事情。

在 JSX 中可以动态地使用 JavaScript 的特性,其最核心的概念就是表达式。表达式是一个会返回一个值的一个 JavaScript 的语法:

  • 第一、JSX 本身就是表达式。上文代码中 element 返回的是一个 HTML 的节点。

  • 第二、在属性中使用表达式。如果我们要给一个组件传递一个属性的值,那么这个属性的值可以是一个 JavaScript 的表达式,可以说是 的表达式,它有一个返回值。

  • 第三、可以使用延展属性。如果要给一个组件传递一组值,不需要一个个去填写,因为可能已经有了一个属性的 Object,我们只需要用 const props = { firstName: 'Ben' , lastName: 'Hector' };const greeting ={…props} /> ; 这种语法。这个其实也不完全是 JSX 独创的语法,这个是 ES6 中就有这种延展的操作符,所以可以去给它传一批属性。

  • 第四、表达式是可以作为子元素的。子元素是 React 的一个特殊属性,这个属性会传给 Children,作为子元素,就需要返回值是一个可 return 的节点,所以说它可能是一个组件 Node,或者是一个原生 Node 的再或者一个字符串等等。

我们可以稍微对比一下其他的模板语言,那来看一下 JSX 究竟是有什么特别之处。

这是一个 Angular 的模板,会在 HTML 标记中给它一些特殊的属性,用一个解释器去解释这些属性,最终来重新组织 UI,这就需要你重新学习一个语言模板,而 JSX 则是不需要去学习的。

我们可以总结一下 JSX 的优点:

  • 第一、可以用声明式的方式去创建界面,是一个非常直观的过程,会有非常多的 HTML 标记,除了原生的还有自己定义的,可以很方便的去描述 UI。

  • 第二、拥有代码创建界面的灵活性,什么时候创建节点、什么时候这个节点应该消失、属性什么时候发生变化,都是像写 JavaScript 代码一样,非常灵活。

  • 第三、可以让你不需要去学习一门新的模板语言,你只要需要了解 JavaScript 语法和 JSX 的特性,就可以立刻用 JSX 来描述组件。

最后,要强调的是 JSX 有一个约定,也是 React 用来区分自定义组件和原生 DOM 节点的一个约定:所有的自定义组件都必须以大写字母开头。

它认为小写的 tag 都是原生的 DOM 节点,比如 div,所有大写字母开头的都是自定义组件,这样 React 会去找这个组件的定义,然后去认得它。

JSX 标记也是可以使用属性的语法的,比如说< menu.Item/ >,就是一个合法的 JSX 的标记,如果是用属性语法,就不需要遵循大写字母开头这样的约定了。

作者说

我是王沛,现担任 eBay 中国研发中心资深技术专家,负责 eBay 内部前端框架的研发。

在 React 16 版本更新后,我发现即使 React 拥有前端框架中最繁荣的生态圈,网上很多中文教程依旧跟不上 React 更新的步伐,甚至很多教程还有很多低级的错误。

于是,我和极客时间一起打磨了《React实战进阶45讲》视频课程,由浅入深地介绍 React 技术栈的基本概念、原理以及设计模式,帮你快速弄懂 React 的关键知识点,熟练使用 React 技术栈构建出复杂的前端应用。

这篇文章便是专栏中第三节课程的内容,学习的过程中我会采用理论讲解加代码演示的方式,在讲清楚概念的同时,结合具体场景,帮你将概念和模式应用到实际案例中,也提供了线上实战项目帮助你熟悉和彻底掌握所学知识。

相信学完本课程后,不论是找工作,还是项目实战,你都能完成一次开发技能精进,甚至掌握开发大型项目的能力。

  订阅方式

扫描下方二维码,即可订阅。


前端之巅

「前端之巅」是 InfoQ 旗下关注大前端技术的垂直社群。紧跟时代潮流,共享一线技术,欢迎关注。


前端之巅

InfoQ大前端技术社群

 
前端之巅 更多文章 SpriteJS:重新定义Canvas API Web前端框架:是解药还是毒药? 前端周报:ECMAScript 2018语言规范新版本发布,苹果三星专利案终和解! 华为快应用引擎技术架构详解 关于Flutter,你想知道的都在这里了!
猜您喜欢 MySQL的大数据改进:支持NoSQL和Hadoop 春假,是每个爹的噩梦 拿代码量算KPI... ...跟程序员们来这套?(上) 从卡顿到秒开:途牛Android端启动优化最佳实践 性能测试应该怎么做?