文章目录[隐藏]
背景
React真是个好东西,不过JS语法有时候还是难免显得臃肿。ES6虽然改进了许多,不过还是有很多槽点。比起来我感觉CoffeeScript就舒服了许多。
React魔改了一番JS,使其能在JS代码中直接插入HTML代码,这样魔改之后的JS叫做JSX。本文对JSX就不做过多的赘述了,我们直接来说CoffeeScript版本的“JSX”——CJSX。虽然说是新姿势,不过其实cjsx已经有一段时间了。不过接下来,我先不介绍CJSX,先行介绍一些的其他的在React中使用CoffeeScript的姿势。
react-coffee
为了让CoffeeScript能舒服的用上React,最简单的方法莫过于把React DOM封装成一个库,然后直接调用。这么做的不止coffee-react一家,不过coffee-react挺具有代表性的,所以我们就拿他来说。以及这个名字和我们主要要介绍的那个库很像,不要搞错了!先来看看官方给出的一段代码示例:
{div}= React.DOM module.exports= React.Component.toComponent class MyComponent render: -> (div null, "My Component!" )
不评论风格美丑,但是要论优雅程度,我觉得还差那么点w
coffee-react
这篇文章的主角就是这个了。直接来看看官方的示例吧:
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-in-browser
这个库是用来在浏览器中直接调试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
在半个多月之前,CS2发布了其第一个正式版本。其中一个重大更新就是——CS原生支持像JSX这样的写法了。于是这篇文章就彻底的作废了。这里是官方传送门:http://coffeescript.org/v2/#jsx。关于CS2的其他更新,我会撰写新的博文。
感谢分享!已推荐到《开发者头条》:https://toutiao.io/posts/dg5jou 欢迎点赞支持!
欢迎订阅《KAAAsS的J&A教室》https://toutiao.io/subjects/69380
代码很复杂的感觉。。