webpack.config.js 加入 cjsx-loader
var production = (process.env.RACK_ENV == 'production')
module.exports = {
...
plugins: (production ? [
new webpack.DefinePlugin({
"process.env": { NODE_ENV: '"production"' } // reduce react size
}),
new webpack.optimize.UglifyJsPlugin(),
] : [
new webpack.HotModuleReplacementPlugin()
]),
module: {
loaders: [
...
{ test: /\.cjsx$/, loader: (production ? 'coffee!cjsx' : 'react-hot!coffee!cjsx') },
匿名 class
React = require 'react'
module.exports = class extends React.Component
render: ->
<div></div>
Comprehension 渲染数组,比 Array.map 更有效率,比 for 循环 push 更简洁
<div>
{ <div key={item.id} onClick={ @props.onDelete.bind null, i }>
Delete {item.name}
</div> for item, i in items }
</div>
利用 pattern matching + for ... by 实现 ruby 中的 each_slice 或者 lodash 的 chunk 的效果
<div>
{ <tr key={a.id + b.id}>
<td>{ a }</td>
<td>{ b }</td>
</tr> for [a, b] in rows by 2 }
</div>
如果 child component 要和 parent 共享 state, 那么应该由 parent 控制 state, 而 child 只需要接受 props, 控制 state 的方法可以由 props 传入
假设有 Page, 有内部状态 items
class Page extends React.Component
getInitialState: ->
items: [{id: 1, name: 'foo'}, {id: 2, name: 'bar'}]
deleteItem: (i) ->
@state.items[i..i] = []
@setState @state
render: ->
<div>
<h1><span>{@state.items.length}</span> items</h1>
<Items key={item.id} items={@state.items} onDelete={@deleteItem} />
</div>
用 Coffee 可以这样实现 Items (func.bind(null, ...)
不改变 this
):
class Items extends React.Component
render: ->
<div>
{ <div key={item.key}>
<a onClick={@props.onDelete.bind null, i}>{item.name}</a>
</div> for item, i in @props.items
}
</div>
或者用 Array.map
class Items extends React.Component
render: ->
<div>
{ @props.items.map (item, i) =>
<div key={item.key}>
<a onClick={=> @props.onDelete i}>{item.name}</a>
</div>
}
</div>
或者用 do 语法...
class Items extends React.Component
render: ->
<div>
{ <div key={item.key}>
<a onClick={do (i) => => @props.onDelete i}>{item.name}</a>
</div> for item, i in @props.items
}
</div>