文章目录[隐藏]
React真是个好东西,不过JS语法有时候还是难免显得臃肿。ES6虽然改进了许多,不过还是有很多槽点。比起来我感觉CoffeeScript就舒服了许多。
React魔改了一番JS,使其能在JS代码中直接插入HTML代码,这样魔改之后的JS叫做JSX。本文对JSX就不做过多的赘述了,我们直接来说CoffeeScript版本的“JSX”——CJSX。虽然说是新姿势,不过其实cjsx已经有一段时间了。不过接下来,我先不介绍CJSX,先行介绍一些的其他的在React中使用CoffeeScript的姿势。
为了让CoffeeScript能舒服的用上React,最简单的方法莫过于把React DOM封装成一个库,然后直接调用。这么做的不止coffee-react一家,不过coffee-react挺具有代表性的,所以我们就拿他来说。以及这个名字和我们主要要介绍的那个库很像,不要搞错了!先来看看官方给出的一段代码示例:
{div}= React.DOM
module.exports= React.Component.toComponent class MyComponent
render: ->
(div null,
"My Component!"
)
不评论风格美丑,但是要论优雅程度,我觉得还差那么点w
这篇文章的主角就是这个了。直接来看看官方的示例吧:
NeatComponent = React.createClass
render: ->
<div className="neat-component">
{<h1>A Component is I</h1> if @props.showTitle}
<hr />
{<p key={n}>This line has been printed {n} times</p> for n in [1..5]}
</div>
简直就是Coffee中的JSX啊!不过可惜的是,这样就需要再编译了。不过其实也无所谓,毕竟cs本身也要编译成js的。不过这里要说明下,因为这篇文章的写作开始的很早,一切都发生了变化……首先就是,这个库停止维护了。目前能达到此功能且依旧在维护的是:https://github.com/jsdf/cjsx-codemod。
这个库是用来在浏览器中直接调试cjsx的,把官网的例子重新写一下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>233333333333</title>
</head>
<body>
<div id="example">
</div>
<script type="text/cjsx">
HelloWorldApp = React.createClass
getInitialState: ->
clock: 0
componentWillMount: ->
setInterval =>
@setState clock: @state.clock+1
, 1000
resetClock: ->
@setState clock: 0
render: ->
<div className="hi">
<h1>Hello, world!</h1>
<p>Seconds elapsed: {@state.clock}</p>
<button
onClick={@resetClock}
disabled={if @state.clock < 2 then 'disabled' else ''}>
Reset
</button>
<ul>
{ <li>{i}</li> for i in [0...@props.listLength] }
</ul>
</div>
React.renderComponent <HelloWorldApp listLength=9 />, document.getElementById('example')
</script>
<script type="text/javascript" src="react-0.11.1.js"></script>
<script type="text/javascript" src="https://rawgit.com/iamdanfox/cjsx-in-browser/master/cjsx-in-browser.js"></script>
</body>
</html>
运行效果大致如下:
这是编译时的中间结果:
HelloWorldApp = React.createClass
getInitialState: ->
clock: 0
componentWillMount: ->
setInterval =>
@setState clock: @state.clock+1
, 1000
resetClock: ->
@setState clock: 0
render: ->
React.DOM.div({"className": "hi"},
React.DOM.h1(null, "Hello, world!"),
React.DOM.p(null, "Seconds elapsed: ", (@state.clock)),
React.DOM.button({ \
"onClick": (@resetClock), \
"disabled": (if @state.clock < 2 then 'disabled' else '')}, """
Reset
"""),
React.DOM.ul(null,
( React.DOM.li(null, (i)) for i in [0...@props.listLength] )
)
)
React.renderComponent HelloWorldApp({"listLength": 9}), document.getElementById('example')
这是最后的状态:
(function() {
var HelloWorldApp;
HelloWorldApp = React.createClass({
getInitialState: function() {
return {
clock: 0
};
},
componentWillMount: function() {
return setInterval((function(_this) {
return function() {
return _this.setState({
clock: _this.state.clock + 1
});
};
})(this), 1000);
},
resetClock: function() {
return this.setState({
clock: 0
});
},
render: function() {
var i;
return React.DOM.div({
"className": "hi"
}, React.DOM.h1(null, "Hello, world!"), React.DOM.p(null, "Seconds elapsed: ", this.state.clock), React.DOM.button({
"onClick": this.resetClock,
"disabled": (this.state.clock < 2 ? 'disabled' : '')
}, "Reset"), React.DOM.ul(null, (function() {
var _i, _ref, _results;
_results = [];
for (i = _i = 0, _ref = this.props.listLength; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
_results.push(React.DOM.li(null, i));
}
return _results;
}).call(this)));
}
});
React.renderComponent(HelloWorldApp({
"listLength": 9
}), document.getElementById('example'));
}).call(this);
在半个多月之前,CS2发布了其第一个正式版本。其中一个重大更新就是——CS原生支持像JSX这样的写法了。于是这篇文章就彻底的作废了。这里是官方传送门:http://coffeescript.org/v2/#jsx。关于CS2的其他更新,我会撰写新的博文。