JSX使用简介
一、JSX简介
JSX 是 JavaScript 语法的扩展,是 Facebook 团队提出的一个语法方案,可以在 JavaScript 的代码直接中使用 HTML 标签来编写 JavaScript 对象,这种语法方案需要通过 JSXTransformer 来进行编译转换成真实可用的 JavaScript 代码。
React 是基于组件的开发思想,React 认为一个组件可以是一个完全独立的没有任何其他依赖的模块文件。一个组件中可以有自己的样式(Inline Style)和结构(JSX编写的HTML)。
二、语法规则
允许 HTML 与 JavaScript 的混写:HTML 语言直接写在 JavaScript 语言之中,不加任何引号,遇到 HTML 标签(以 < 开头),就用 HTML 规则解析;遇到代码块(以 { 开头),就用 JavaScript 规则解析。
使用JSX来创建一个HTML标签,首字母小写:
var link = <a href="xxx">Hello World!</a>
使用JSX来创建一个React组件:
var HelloWorld = <HelloWorld foo="bar"></HelloWorld>
备注
-
React 的 JSX 里约定分别使用首字母大、小写来区分React组件和 HTML 标签。
-
由于JSX 是直接将 HTML 写在 JavaScript 代码中,如果HTML 中的属性是 JavaScript 的关键字,则必须进行转换,转换规则和在 JavaScript 中使用 DOM 的 property 一样。例如 class 和 for 使用 className 和 htmlFor 来代替。
-
JSX 标签的标签都需要有完整的结束符号,否则编译会报错。
三、基本语法
1、变量
JSX中可以通过 {xxx}
来插入一个JavaScript变量:
var message = 'Hello World!';
<span>{message}</span>
2、根节点
每一段JSX代码都只能有一个根节点,否则编译不通过,尤其是多行语句的时候。
var btnBox = (
<div>
<button>Click me</button>
<p>Hello World!</p>
</div>
);
3、表达式
JSX中支持三元表达式:
var person = <Person name={window.isLoggedIn ? window.username : ''}/>
var content = <Container>{window.isLoggedIn ? <Nav/> : <Login/>}</Container>
4、流程控制
if-else
在JSX中不能直接在{}中使用if-else,可以使用三元表达式代替:
<div>{locale === 'zh-CN' ? '您好!' : 'Hello'}</div>
三元表达式往往并不能满足需求,React建议在JS代码中使用if-else
,如下:
var button;
if(window.isLoggedIn){
button = <LogoutButton/>
}else{
button = <LoginButton/>
}
reutrn (
<nav>
<Home/>
{button}
</nav>
);
switch-case
<p>
{(()=>{
switch(this.state.color){
case "red":
return "#f00";
case "green":
return "#0f0";
case "blue":
return "#00f";
default:
return "#fff";
}
})()}
</p>
例子中使用了es6的箭头函数语法。
for
var toolbar = [];
for(var i = 0; i < buttons.length; i++){
toolbar.push(<LinkButton key={i}/>);
}
return (
<div id="toolbar">{toolbar}</div>
);
5、JSX中使用样式
在JSX中使用样式和HTML中很类似,通过style属性来定义,不同的是,属性值不能是字符串而必须为对象。
在JSX中可以使用所有的的样式,属性名的转换规范就是将其写成驼峰写法,例如background-color
变为backgroundColor
, font-size
变为fontSize
,这和标准的JavaScript操作DOM样式的API是一致的。
<div style={ {color:"#000",fontSize:"14px"} }></div>
//或先将样式定义为变量再使用
var style = {color:"#000",fontSize:"14px"};
return (
<div style={style}>HelloWorld!</div>
);
6、JSX中绑定事件
JSX 中的事件绑定和原生HTML定义事件基本一致,唯一的区别是JSX采用驼峰写法来描述事件名称,大括号中仍然是标准的JavaScript表达式,返回一个事件处理函数。
<button onClick={this.handleClick}>Click me</button>
React并不会真正的绑定事件到每一个具体的元素上,而是采用事件代理的模式:在根节点document上为每种事件添加唯一的Listener,然后通过事件的target找到真实的触发元素。这样从触发元素到顶层节点之间的所有节点如果有绑定这个事件,React都会触发对应的事件处理函数。这就是所谓的React模拟事件系统。尽管整个事件系统由React管理,但是其API和使用方法与原生事件一致。
7、展开操作符
在JSX中可以使用类似于ES6的展开操作符...
var props = {foo: "x", bar: "y"};
var component = <Component {...props}/>;
展开操作符也可以和其它属性一起使用:
var props = {foo: "default"};
var component = <Component {...props} foo="override"/>;//后面的属性值会覆盖掉前面的
console.log(component.props.foo);//override
8、HTML转义
由于为了防止各种 XSS 攻击, React 默认会转义所有字符串。如果想直接使用原始 HTML,可以使用dangerouslySetInnerHTML
属性。如果不到万不得已,不建议这么做。
var htmlContent = '<a href="https://baidu.com">Baidu</a>';
var component = <span dangerouslySetInnerHTML={ { __html: htmlContent} } />;
9、自定义HTML属性
如果往原生 HTML 元素里传入 HTML 规范里不存在的属性,React 不会显示它们。如果需要使用自定义属性,要加 data-
前缀。
以 aria- 开头的 [网络无障碍] 属性可以正常使用。
<div data-custom-attribute="foo"/>
<div aria-hidden={true}/>
10、命名空间
JSX中还可以支持组件的命名空间,可以让组件的层次更清晰,更语义化。
var Form = React.createClass({
render: function(){
return <form className="myform">{this.props.children}</form>;
}
});
Form.Row = React.createClass({
render: function(){
return (<div className="myrow">{this.props.children}</div>);
}
});
Form.Label = React.createClass({
render: function(){
return <label htmlFor="message" className="mylabel">留言:</label>
}
});
Form.Input = React.createClass({
render: function(){
return <input id="message" className="myinput" placeholder="请输入留言信息"/>;
}
});
var App = (
<Form>
<Form.Row>
<Form.Label />
<Form.Input />
</Form.Row>
</Form>
);
11、JSX中特殊的false
false
在 JSX 中的不同位置有不同作用 。id={false}
和 value={false}
都换转换成字符串 false
, disabled={false}
是设置 disabled 属性为 false
, <p>{false}</p>
表示该 p 标签没有子元素。
<div id={false}>
<input type="text" name="name" value={false}/>
<button disabled={false}>Click me</button>
<p>false</p>
</div>
12、注释
JSX中的注释需要写在花括号中:
return (
<Nav>
{/*comment*/}
{/*
comments
*/}
<Person name={window.isLoggedIn ? window.name : ''}/>
</Nav>
);
四、JSX Transform
JSX 把类 XML 的语法转成原生 JavaScript,XML 元素、属性和子节点被转换成 React.createElement 的参数。
var Nav;
//输入(JSX)
var app = <Nav color="blue"/>
//输出(JS)
var app = React.createElement(Nav, {color:"blue"});
JSX中也支持使用XML语法定义子结点:
var Nav, Profile;
//输入(JSX)
var app = <Nav color="blue"><Profile>profile</Profile></Nav>;
//输出(JS)
var app = React.createElement(
Nav,
{color:"blue"},
React.createElement(Profile, null, "profile");
);
浏览器中的JSX转换器是相当大的,并且会在客户端导致无谓的计算,这些计算是可以避免的。不要在生产环境直接使用JSX,应该使用 react-tools 等工具预编译JSX后再使用。
五、代码风格建议
为了代码有更好的可读性,无论是单行语句还是多行语句,都建议使用 () 来包裹 JSX 语句。在 JSX 中插入 JavaScript 语句的时候尽量不要嵌套太长的三目运算符,JSX 本身就是为了开发更简便和更好的维护性。