雨夜带刀's Blog

React 的骨架 JSX

为什么需要JSX

JSX 是 Facebook 团队提出的一个语法方案,可以在 JavaScript 的代码直接中使用 HTML 标签来编写 JavaScript 对象。其使用的是 XML-like 语法,这种语法方案需要通过 JSXTransformer 来进行编译转换成真实可用的 JavaScript 代码(React 官方已经推荐使用 babel 来代替)。

React 是基于组件的开发思想,React 认为一个组件可以是一个完全独立的没有任何其他依赖的模块文件。一个组件中可以有自己的样式(Inline Style)和结构(JSX编写的HTML)。

在 React 和 JSX 之前,一个组件如果要包含 HTML 结构将面临如下几个问题:

  • 1. 组件的 HTML 直接写在页面中,那么组件的结构和行为是分离的;

  • 2. 组件的 HTML 直接用字符串的形势插入到 JavaScript 代码中,那么就会出现一大段的字符串拼接,开发人员需要很小心的确保字符串拼接时没有因为少了一个符号而导致整个代码无法运行;

  • 3. 使用 MVC 分层的思想,引入模板引擎,那么该如何引入模板文件的片段呢;

JSX 很好的解决了这些问题。

基本语法

使用 JSX 来创建一个 HTML 标签,首字母小写:

var link = <a href="xxx">Hello World!</a>;

相当于调用了 React.createElement 方法:

var link = React.createElement('a', {href: 'xxx'}, 'Hello World!')

使用 JSX 来创建一个 Component,首字母大写:

var HelloWorld = <HelloWorld foo="bar"></HelloWorld>

首字母的大小写有严格的区分,这样 JSX 可以很简单的通过区分首字母是小写还是大写来判断转换的是 HTML 标签还是自定义的 Component。

JSX 标签的标签都需要有完整的结束符号,否则编译会报错。

<div></div>
<input type="text" />

变量和逻辑

JSX 中可以通过 {xxx} 来插入一个 JavaScript 变量:

var name = 'xiao ming';
<a href="xxx">Hello {name}!</a>

没错,HTML 语法就是这样和 JavaScript 语法无缝的结合!

如果要在 JSX 中插入一段 JavaScript 代码,那么一次只能插入一个一次就能执行完的语句。

var link = <a href="xxx">Hello {if (conditions) {'xiao ming'}}!</a>

上面的代码编译后会是这样的:

var link = React.createElement('a', {href: 'xxx'}, if (conditions) {'xiao ming'})

编译后可以看到明显存在语法错误,可以使用三元运算符来将条件判断语句简化成一个语句:

var link = <a href="xxx">Hello {conditions ? 'xiao ming' : ''}!</a>

多行语句和根节点

无论你的 JSX 代码有多长,每一段代码都只能有一个根节点,否则编译通不过,因为 React 需要确保一个组件只能有一个根节点。

// 错误的写法
var btnBox = (
    <button>Click me</button>
    <p>hello world!</p>
);

// 正确的写法
var btnBox = (
    <div>
        <button>Click me</button>
        <p>hello world!</p>
    </div>
);

如果想在 JSX 中添加注释,需要使用多行注释的语法并确保其包裹在 {} 中。

<div>
    <h3>title</h3>
    {/*<p>text</p>/*}
</div>

关键字冲突

因为 JSX 是直接将 HTML 写在 JavaScript 代码中,如果在 HTML 中有的属性中有 JavaScript 的关键字,必须进行转换,转换规则和在 JavaScript 中使用 DOM 的 property 一样。如 class 需转换成 classNamefor 要转换成 htmlFor,还有其他的关键字这里不做一一列举。

false in JSX

false 在 JSX 中,会有不同的作用。

 <div id={false}>
    <input type="text" name="name" value={false} />
    <button type="button" name="button" disabled={false}>hello</button>
    <p>{false}</p>
</div>

id={false}value={false} 都换转换成字符串 falsedisabled={false} 是设置 disabled 属性为 false<p>{false}</p> 表示该 p 标签没有子元素。

Inline Style

上面提到过 React 希望一个组件中可以是独立的,可以将样式直接通过 JavaScript 的对象插入到 JSX 中,这样就可以给一个组件定义样式了。

var paraStyle = {
    color: '#fff',
    fontSize: '14px'
};

var para = (
    <p style={paraStyle}></p>
);

在定义样式的时候,对象的 key 就是样式的属性,属性中如果有中划线,需将其换成驼峰式,value 就是对应的属性值。对于一些复杂的伪类选择器,以及其他的一些高级的 CSS 特性,有相应的库可以对其支持。

将样式通过内联的形式写在组件内部,虽然有违分离原则,但是其确实解决了因为分离带来的组件独立性的问题,虽然是反模式化的,但确确实实解决了一个痛点。

命名空间

JSX 中还可以支持组件的命名空间,可以让组件的层次更清晰,更语义化。

var Form = React.createClass({ ... });
Form.Row = React.createClass({ ... });
Form.Label = React.createClass({ ... });
Form.Input = React.createClass({ ... });

var App = (
    <Form>
        <Form.Row>
            <Form.Label />
            <Form.Input />
        </Form.Row>
    </Form>
);

代码风格建议

为了代码有更好的可读性,无论是单行语句还是多行语句,都建议使用 () 来包裹 JSX 语句。在 JSX 中插入 JavaScript 语句的时候尽量不要嵌套太长的三目运算符,JSX 本身就是为了开发更简便和更好的维护性。如果把 JSX 也写成一坨一坨可读性很差的代码,实在太不应该了。

原载于:雨夜带刀’s Blog
本文链接:http://stylechen.com/react-jsx.html
如需转载请以链接形式注明原载或原文地址。

“React 的骨架 JSX”目前已有 3 条评论

发表评论:

  • *
  • *
头像

雨夜带刀

前端开发工程师,技术宅,现居北京。

雨夜带刀的开源项目

easy.js
一个简洁的 JavaScript 类库,集成了模块加载器,同时也有包含了常见的的组件库,可访问项目网站
seed
符合 AMD 规范的 JavaScript 模块加载器。
ecope
从 easy.js 组件库中移值过来的基于 jQuery 的组件库,简单实用,API 风格统一。