简介
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 么?