[关闭]
@ttingtu 2015-12-22T07:21:19.000000Z 字数 4488 阅读 2032

JSX相关

深入JSX

HTML标签和React组件

React既可以渲染HTML标签,也可以渲染React组件。
在JSX语法中,html标签一般以小写字母打头,如:

  1. var myDivElement = <div className="foo" />;
  2. ReactDOM.render(myDivElement, document.getElementById('example'));

在React组件中,一般是先定义一个以大写字打头的本地变量,使用时在<>中写上变量名即可,如下

  1. var MyComponent = React.createClass({/*...*/});
  2. var myElement = <MyComponent someProperty={true} />;
  3. ReactDOM.render(myElement, document.getElementById('example'));

注: jsx也属于javascript,class和for两个属性为javascript的关键字,在定义 React组件时,应将其分别写成className和htmlFor。

将React jsx转化成javascript

JSX语法写成的语句,都会被转化成原生的javascript里的xml元素,其属性和子节点将作为参数传递给React.createElement方法。如

  1. var Nav;
  2. // Input (JSX):
  3. var app = <Nav color="blue" />;
  4. // Output (JS):
  5. var app = React.createElement(Nav, {color:"blue"});

定义 了一个名字为Nav的React组件。通过jsx可以直接写成:var app = < Nav color="blue" />; 与纯javascript写的:var app = React.createElement(Nav, {color:"blue"}); 意思是一样的。

JSX也允许指定子节点,如

  1. var Nav, Profile;
  2. // Input (JSX):
  3. var app = <Nav color="blue"><Profile>click</Profile></Nav>;
  4. // Output (JS):
  5. var app = React.createElement(
  6. Nav,
  7. {color:"blue"},
  8. React.createElement(Profile, null, "click")
  9. );

当组件的displayName属性没有定义时,其默认值为变量名,如

  1. // Input (JSX):
  2. var Nav = React.createClass({ });
  3. // Output (JS):
  4. var Nav = React.createClass({displayName: "Nav", });

Namespaced 组件

如果定义一个组件有许多个子组件,比如form,必须得声明多个变量,如

  1. // Awkward block of variable declarations
  2. var Form = MyFormComponent;
  3. var FormRow = Form.Row;
  4. var FormLabel = Form.Label;
  5. var FormInput = Form.Input;
  6. var App = (
  7. <Form>
  8. <FormRow>
  9. <FormLabel />
  10. <FormInput />
  11. </FormRow>
  12. </Form>
  13. );

这样看起来很麻烦,为了简单和方便,可以使用namespaced 组件。定义时可将子组件定义为父组件的属性,如下

  1. var MyFormComponent = React.createClass({ ... });
  2. MyFormComponent.Row = React.createClass({ ... });
  3. MyFormComponent.Label = React.createClass({ ... });
  4. MyFormComponent.Input = React.createClass({ ... });

使用时,可通过如下方式

  1. var Form = MyFormComponent;
  2. var App = (
  3. <Form>
  4. <Form.Row>
  5. <Form.Label />
  6. <Form.Input />
  7. </Form.Row>
  8. </Form>
  9. );

JSX能正确编译代码:

  1. var App = (
  2. React.createElement(Form, null,
  3. React.createElement(Form.Row, null,
  4. React.createElement(Form.Label, null),
  5. React.createElement(Form.Input, null)
  6. )
  7. )
  8. );

**该功能只在V0.11及以上版本提供。 **

javascript表达式

表达式 属性

JSX语法中,使用javascript表达式作为属性值 时,必须将表达式以{}括起来,而不能直接用""

  1. // Input (JSX):
  2. var person = <Person name={window.isLoggedIn ? window.name : ''} />;
  3. // Output (JS):
  4. var person = React.createElement(
  5. Person,
  6. {name: window.isLoggedIn ? window.name : ''}
  7. );

boolean属性

JSX 中,如果不写某个属性的值,那么其值默认为true。 即如果想要某个属性值 为true,要么不赋给它值 ,要么使用{true},如果想要某个属性值 为false,要么不写该属性,要么将其值设置为{false},比如给html里的form标签设置disabled, required,checked,readonly属性时:

  1. // These two are equivalent in JSX for disabling a button
  2. <input type="button" disabled />;
  3. <input type="button" disabled={true} />;
  4. // And these two are equivalent in JSX for not disabling a button
  5. <input type="button" />;
  6. <input type="button" disabled={false} />

子节点

也可以通过javascript表达式增加子节点,如

  1. // Input (JSX):
  2. var content = <Container>{window.isLoggedIn ? <Nav /> : <Login />}</Container>;
  3. // Output (JS):
  4. var content = React.createElement(
  5. Container,
  6. null,
  7. window.isLoggedIn ? React.createElement(Nav) : React.createElement(Login)
  8. );

添加注释

// 注释一行
/* */注释一段代码。
但需要特别注意的是:如果在标签子节点前添加注释时,需要将注释以{}包围。如

  1. var content = (
  2. <Nav>
  3. {/* child comment, put {} around */}
  4. <Person
  5. /* multi
  6. line
  7. comment */
  8. name={window.isLoggedIn ? window.name : ''} // end of line comment
  9. />
  10. </Nav>
  11. );

JSX传播属性

如果事先知道组件的所有属性值,可以如下使用JSX:

  1. var component = <Component foo={x} bar={y} />;

最好不要先声明组件,再声明其属性值,类似如下的声明最好不要用:

  1. var component = <Component />;
  2. component.props.foo = x; // bad
  3. component.props.bar = y; // also bad

可通过如下方式声明:

  1. var props = {};
  2. props.foo = x;
  3. props.bar = y;
  4. var component = <Component {...props} />;

对象props的属性值是复制给Component的属性的,因此是不可变的。**注意使用...操作符(ES6数组中也支持...操作符)**props可以多次使用,也可以与其他属性一起使用。 属性赋值的顺序很重要,后赋值的属性会覆盖之前赋值的属性。

  1. var props = { foo: 'default' };
  2. var component = <Component {...props} foo={'override'} />;
  3. console.log(component.props.foo); // 'override'

JSX进阶

JSX看起来像html但与html有些许不同。

HTML特殊字符

可以直接在JSX中插入HTML特殊字符:

  1. <div>First &middot; Second</div>

React会转义所有的字符串来防止XSS攻击,因此如果需要动态展示HTML特殊字符,在{}中写入转义字符,最后可能并不能正确显示,如

  1. // Bad: It displays "First &middot; Second"
  2. <div>{'First &middot; Second'}</div>

如果需要在{}中展示html特殊字符有如下几种办法:
- 最简单的方法,直接在javascript中写入特殊字符,不使用转义,但是必须确保文件以UTF-8格式保存,并且浏览器能正确显示

  1. <div>{'First · Second'}</div>
  1. <div>{'First \u00b7 Second'}</div>
  2. <div>{'First ' + String.fromCharCode(183) + ' Second'}</div>
  1. <div>{['First ', <span>&middot;</span>, ' Second']}</div>
  1. <div dangerouslySetInnerHTML={{__html: 'First &middot; Second'}} />

定制的HTML属性

如果向HTML元素中传入一些自定义的属性,React并不会对其进行渲染。如果需要使用自定义属性,最好加上data-前缀

  1. <div data-custom-attribute="foo" />

如果是在自定义元素上使用自定义属性也是支持的,属性前面不需要加data-前缀。

  1. <x-my-component custom-attribute="foo" />

web相关的属性即以aria-前缀的属性能够被react正确渲染,如:

  1. <div aria-hidden={true} />

参考资料:
- http://facebook.github.io/react/docs/jsx-in-depth.html
- http://facebook.github.io/react/docs/jsx-spread.html
- http://facebook.github.io/react/docs/jsx-gotchas.html

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注