最近几个月作的一个项目,使用了react技术体系,天然而然的用到了JSX。下面就总结一下本身对JSX的认识。javascript
即JavaScript XML,一种在React组建内部构建标签的类XML语法。(加强React程序组件的可读性)php
JSX能够看做JavaScript的拓展,看起来有点像XML。使用React,能够进行JSX语法到JavaScript的转换。css
下面咱们来看一下一个简单的例子。
考虑一下这个变量的声明:html
const element = <h1>Hello, world!</h1>;
这个标签语法既不是字符串也不是HTML,这就是JSX。它是JavaScript的一种扩展语法。前端
咱们先从官网的一个最简单的例子提及,为了让你们可以直接在本地运行,我贴出了完整的代码以下:java
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>Hello React!</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react-dom.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script> </head> <body> <div id="example"></div> <script type="text/babel"> const element = <h1>Hello, world!</h1>; ReactDOM.render( element, document.getElementById('example') ); </script> </body> </html>
你们能够直接粘贴上面代码,保存在本地的一个test.html文件里,双击打开后,在浏览器里输出:node
Hello, world!react
咱们看到git
const element = <h1>Hello, world!</h1>;
element变量的声明就是用了JSX语法,HTML语言直接写在JavaScript语言之中,不加任何引号。github
注意:
script
标签的 type
属性为 text/babel
,这是React 独有的 JSX 语法,跟 JavaScript 不兼容。凡是在页面中直接使用 JSX 的地方,都要加上 type="text/babel"
。
一共用了三个库: react.js 、react-dom.js 和 browser.min.js ,它们必须首先加载。其中,react.js 是 React 的核心库,react-dom.js 是提供与 DOM 相关的功能, browser.min.js的做用是将 JSX 语法转为 JavaScript 语法。
好比要建立一个dom超连接:
<a class="link" href="https://github.com/facebook/react">React<a>
咱们在原生DOM中,用js构造dom的方式是这样的:
var a = document.createElement('a') a.setAttribute('class', 'link') a.setAttribute('href', 'https://github.com/facebook/react') a.appendChild(document.createTextNode('React'))
这个代码应该是你们比较熟悉的。当你在写代码的时候会不会感受很繁琐呢,咱们能够封装一下:
//第一个参数为node名 //第二个参数为一个对象,dom属性与事件都以键值对的形式书写 //第三个到第n个为子node,它们将按参数顺序出现, //在这个例子中只有一个子元素,并且也是文本元素,因此能够直接书写,不然还得React.createElement一下 var a = React.createElement('a', { className: 'link', href: 'https://github.com/facebook/react' }, 'React')
看完这个代码,是否是感受一会儿要简洁的多。
如今有个编译工具,可让你用html语法来写React.createElement,部署上线前编译回来。你愿意吗?
无论你的答案是什么,但这就是jsx的一半真相。
前面已经回答过,在使用React的时候,能够不使用JSX,大概这样写:
var child1 = React.createElement('li', null, 'First Text Content'); var child2 = React.createElement('li', null, 'Second Text Content'); var root = React.createElement('ul', { className: 'my-list' }, child1, child2);
使用这样的机制,咱们彻底能够用JavaScript构建完整的界面DOM树,正如咱们能够用JavaScript建立真实DOM。但这样的代码可读性并很差,因而React发明了JSX
,利用咱们熟悉的HTML语法来建立虚拟DOM:
var root =( <ul className="my-list"> <li>First Text Content</li> <li>Second Text Content</li> </ul> );
总结
这两段代码是彻底等价的,后者将XML语法直接加入到JavaScript代码中,让你可以高效的经过代码而不是模板来定义界面。
以后JSX经过翻译器转换到纯JavaScript再由浏览器执行。
注意
在实际开发中,JSX在产品打包阶段都已经编译成纯JavaScript,JSX的语法不会带来任何性能影响。
另外,因为JSX只是一种语法,所以JavaScript的关键字class, for等也不能出如今XML中,而要如例子中所示,使用className, htmlFor代替,这和原生DOM在JavaScript中的建立也是一致的。
相信你们在看完了上面的这些举例后,心中的疑问天然而然就迎刃而解了。
所以,JSX自己并非什么高深的技术,能够说只是一个比较高级但很直观的语法糖。它很是有用,却不是一个必需品,没有JSX的React也能够正常工做:只要你乐意用JavaScript代码去建立这些虚拟DOM元素。
看了上面的这些简单的demo,你们确定会抛出这样的疑问:
为何React官方推荐使用JSX呢?
等等。。。
使用React,不必定非要使用JSX语法,可使用原生的JS进行开发。
可是React做者强烈建议咱们使用JSX,由于:
JSX在定义相似HTML这种树形结构时,十分的简单明了。
简明的代码结构更利于开发和维护。
XML有着开闭标签,在构建复杂的树形结构时,比函数调用和对象字面量更易读。
可能说这些你会感受比较模糊,下面来举几个看得见的例子。
前端界面的最基本功能在于展示数据,为此大多数框架都使用了模板引擎,
<div ng-if="person != null"> Welcome back, <b>{{person.firstName}} {{person.lastName}}</b>! </div> <div ng-if="person == null"> Please log in. </div>
{{#if person}} Welcome back, <b>{{person.firstName}} {{person.lastName}}</b>! {{else}} Please log in. {{/if}}
模板能够直观的定义UI来展示Model中的数据,你没必要手动的去拼出一个很长的HTML字符串,几乎每种框架都有本身的模板引擎。
传统MVC框架强调界面展现逻辑和业务逻辑的分离,所以为了应对复杂的展现逻辑需求,这些模板引擎几乎都不可避免的须要发展成一门独立的语言。
如上面代码所示,每一个框架都有本身的模板语言语法。而这无疑增长了框架的门槛和复杂度。
使用JSX
正由于如此,React直接放弃了模板而发明了JSX。看上去很像模板语言,但其本质是经过代码来构建界面,这使得咱们再也不须要掌握一门新的语言就能够直观的去定义用户界面:掌握了JavaScript就已经掌握了JSX。
这里不妨再引用以前文章举过的例子,在展现一个列表时,模板语言一般提供名为Repeat的语法,例如在Angular中:
<ul class="unstyled"> <li ng-repeat="todo in todoList.todos"> <input type="checkbox" ng-model="todo.done"> <span class="done-{{todo.done}}">{{todo.text}}</span> </li> </ul>
而使用JSX,则代码以下:
var lis = this.todoList.todos.map(function (todo) { return ( <li> <input type="checkbox" checked={todo.done}> <span className={'done-' + todo.done}>{todo.text}</span> </li> ); }); var ul = ( <ul class="unstyled"> {lis} </ul> );
能够看到,JSX完美利用了JavaScript自带的语法和特性,咱们只要记住HTML只是代码建立DOM的一种语法形式,就很容易理解JSX。
而这种使用代码构建界面的方式,彻底消除了业务逻辑和界面元素之间的隔阂,让代码更加直观和易于维护。
你能够用 花括号 把任意的 JavaScript 表达式 嵌入到 JSX 中。
例如,2 + 2, user.firstName, 和 formatName(user),这些都是可用的表达式。
function formatName(user) { return user.firstName + ' ' + user.lastName; } const user = { firstName: 'Harper', lastName: 'Perez' }; const element = ( <h1> Hello, {formatName(user)}! </h1> ); ReactDOM.render( element, document.getElementById('root') );
编译以后,JSX 表达式就变成了常规的 JavaScript 对象。
这意味着你能够在 if 语句或者是 for 循环中使用 JSX,用它给变量赋值,当作参数接收,或者做为函数的返回值。
function getGreeting(user) { if (user) { return <h1>Hello, {formatName(user)}!</h1>; } return <h1>Hello, Stranger.</h1>; }
您可使用双引号来指定字符串字面量做为属性值:
const element = <div tabIndex="0"></div>;
您也能够用花括号嵌入一个 JavaScript 表达式做为属性值:
const element = <img src={user.avatarUrl}></img>;
注意
在属性中嵌入 JavaScript 表达式时,不要使用引号来包裹大括号。不然,JSX 将该属性视为字符串字面量而不是表达式。
对于字符串值你应该使用引号,对于表达式你应该使用大括号,但二者不能同时用于同一属性。
若是是空标签,您应该像 XML 同样,使用 />当即闭合它:
const element = <img src={user.avatarUrl} />;
JSX 标签可能包含子元素:
const element = ( <div> <h1>Hello!</h1> <h2>Good to see you here.</h2> </div> );
在JSX中嵌入用户输入是安全的:
const title = response.potentiallyMaliciousInput; // This is safe: const element = <h1>{title}</h1>;
默认状况下, 在渲染以前, React DOM 会格式化(escapes) JSX中的全部值。
从而保证用户没法注入任何应用以外的代码。
在被渲染以前,全部的数据都被转义成为了字符串处理。 以免 XSS(跨站脚本) 攻击。
Babel 将JSX编译成 React.createElement() 调用。
下面的两个例子是是彻底相同的:
const element = ( <h1 className="greeting"> Hello, world! </h1> );
const element = React.createElement( 'h1', {className: 'greeting'}, 'Hello, world!' );
React.createElement() 会执行一些检查来帮助你编写没有bug的代码,但基本上它会建立一个以下所示的对象:
// 注意: 这是简化的结构 const element = { type: 'h1', props: { className: 'greeting', children: 'Hello, world' } };
关于JSX的介绍大概讲到这里,看完这篇文章后,但愿你们能可以了解什么是JSX,React为何推荐使用JSX等问题。
在下一节中来探索如何将 React 元素渲染到 DOM 上。
欢迎你们访问个人blog,有更精彩的文章吆!
参考连接