简介

  JSX 是点缀着 XML 元素的 JavaScript。它是由 React 这个库最初构思出来的,但又不是专门为了某个库或者框架设计的。它是一种 DSL。

  JSX 是 html in JavaScript 的一种很好体现。这里的 XML,实际上还是 html 元素。粗略看下来,和当初 backbone 写 rendertemplate 的函数差不多。要引入 JSX 的语法,在很多场景下都要引入 Babel 这个 transpiler,也就是要搞到工具链满天飞。照抄官网的例子的话,可以看到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello React!</title>
<script src="vendor-js/react.js"></script>
<script src="vendor-js/react-dom.js"></script>
<script src="vendor-js/babel-core/browser.min.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/babel">
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
</script>
</body>
</html>

  可以看到,<h1>Hello, world!</h1>本来是不应该出现在 javascript 语句中的,它又不是合法的 identifier,又不是合法的 keyword。但后来 compiler 和 transpiler 就可以把它转化成这种实际的形式:

1
2
3
4
5
6
<script type="text/javascript">
ReactDOM.render(
React.DOM.h1(null,'hello,world!'),
document.getElementById('example')
);
</script>

  注意,这个过程应该是类型安全的,即在运行以前就能检查出组件内的错误。

  如果使用纯粹的 React 形式的 JSX 的话,还需要满足两个条件:

  • <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 语法。

  JSX 的特点是,结合了 Javascript 的强表达能力,和 XML 的结构能力。把两种抽象糅合在一起。每一个组件必须附带一个 render 函数(Vue 和 Ember 也都支持)。

   React 组件的命名规范里,自定义的组件首字母大写,html 标签首字母小写。这点也很像 Ember。

   一个一看就懂的动态组件的写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var MyComponent=React.createClass({
getInitialState: function() {
return {clickNum: 0};
},
handleClick:function(){
var num=this.state.clickNum;
num++;
this.setState({clickNum:num});
},
render: function() {
return (
<div>
<h1 onClick={this.handleClick}>Hello {this.props.name}!</h1>
<h2 style={{color:'red'}}>点击{this.props.name}次数:{this.state.clickNum}</h2>
</div>
);
}
});
ReactDOM.render(
<div>
<MyComponent name="张三" />
<hr/>
<MyComponent name="李四" />
</div>,
document.getElementById('example')
);

   JSX 表达的是是虚拟 dom,而不是 html。虚拟 dom 特别像虚拟内存。在虚拟内存中,malloc() 的时候并不会真的对物理内存产生影响。但发生 paging,page error 的时候,虚拟内存就会真的试图往物理内存里调度内存页。virtual Dom 也只是在插入文档后,才变成真正的 DOM,才可以通过 this.refs.[refName]引用真正 DOM 节点。如:

1
2
3
4
5
6
7
8
9
10
11
12
13
var MyComponent = React.createClass({
handleClick: function() {
this.refs.myTextInput.focus();
},
render: function() {
return (
<div>
<input type="text" ref="myTextInput" />
<input type="button" value="Focus the text input" onClick={this.handleClick} />
</div>
);
}
});

  {}抱起来的 expression 可以在 JSX 语法中内插(interpolate)使用。但这个大括号包裹的必须是 expression,而不能是无返回值的 statement。我们可以把这种{}看做一种特殊的语法糖,因此也不能直接使用 if 和 for 语句。work-around 的解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
var HelloMessage = React.createClass({ 
render: function() {
return <div>Hello {
(function(obj){
if(obj.props.name)
return obj.props.name
else
return "World"
}(this))
}</div>;
}
});
ReactDOM.render(<HelloMessage name="xiaowang" />, document.body);

  本文的例子大部分来自于React基础——JSX语法

  另一个基于菜鸟教程的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>菜鸟教程 React 实例</title>
<script src="https://cdn.bootcss.com/react/15.4.2/react.min.js"></script>
<script src="https://cdn.bootcss.com/react/15.4.2/react-dom.min.js"></script>
<script src="https://cdn.bootcss.com/babel-standalone/6.22.1/babel.min.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/babel">
var a = "这是一个变量"
ReactDOM.render(
<div>
{a}
</div>
, document.getElementById('example'))
</script>
</body>
</html>

调试问题

  debug 怎么办,是 debug transpile 以前的还是以后的?有很好的 sourceMap 么?