【教學】使用 LiveScript 寫 ReactJS/Native 應用

LiveScript 是我很喜歡的 "compile to JavaScript" 語言,其簡潔程度可以讓我省去很多時間成本。

目前它沒有像 JSX 的 transformer,在寫 React 的時候可能只能用原生的方式來寫,但感覺起來不會像原本的 JS 寫法難維護。

使用 React.DOM 的方式,或者是 createFactory 來生成元素的 factory

require! react: React

table = React.DOM.table
# or
table = React.create-factory \table

tr = React.create-factory \tr
td = React.create-factory \td

page = React.create-class do
  render: ->
    table null,
      tr null,
        td null, \1
        td null, \2
      tr null
        td null, \3
        td null, \4

自己不是很喜歡 xml,連寫 html 都是用 jade,所以這樣對我來說剛好。
(雖然很多 null 會有點煩,不過在 attr 多的時候不會常見到,或是可以用 {} 代替)

如果覺得 xml 比較好區分邏輯和 view,也是可以用用看 coffee 的 transform
不過有個問題是在標籤如果以 backslash(\) 開頭作為字串的話,也會被 parse 掉。(以單雙引號來說不會,所以其實不算大問題)

str = \<div></div>

# cjsx-transform result
str = \React.createElement("div", null)

拿來寫 React Native 也是爽度很高的一件事,你可以用 React.createFactory 帶入 component 來生成 factory
直接把官方的 Tutorial 範例改用 livescript 來寫

'use strict'

require! \react-native : React

{
  AppRegistry
  Image
  ListView
  StyleSheet
  Text
  View
} = React

image = React.create-factory Image
listview = React.create-factory ListView
view = React.create-factory View
text = React.create-factory Text

API_KEY = \7waqfqbprs7pajbz28mqf6vz
API_URL = \http://api.rottentomatoes.com/api/public/v1.0/lists/movies/in_theaters.json
PAGE_SIZE = 25
PARAMS = "?apikey=#{API_KEY}&page_limit=#{PAGE_SIZE}"
REQUEST_URL = API_URL + PARAMS

AwesomeProject = React.create-class do
  getInitialState: ->
    dataSource: new ListView.DataSource do
      rowHasChanged: (row1, row2) -> row1 is not row2
    loaded: false

  componentDidMount: ->
    @fetchData!

  fetchData: ->
    fetch REQUEST_URL
      .then (response) -> response.json!
      .then (responseData) ~>
        @setState do
          dataSource: @state.dataSource.cloneWithRows responseData.movies
          loaded: true
      .done!

  render: ->
    return @renderLoadingView! if not @state.loaded

    listview do
      dataSource: @state.dataSource
      renderRow: @renderMovie
      style: styles.listView

  renderLoadingView: ->
    view do
      style: styles.container
      text null, 'Loading movies...'

  renderMovie: (movie) ->
    view do
      style: styles.container
      image do
        source: { uri: movie.posters.thumbnail }
        style: styles.thumbnail
      view do
        style: styles.rightContainer
        text do
          style: styles.title
          movie.title
        text do
          style: styles.year
          movie.year

styles = StyleSheet.create do
  container:
    flex: 1
    flexDirection: \row
    justifyContent: \center
    alignItems: \center
    backgroundColor: \#F5FCFF
  rightContainer:
    flex: 1
  title:
    fontSize: 20
    marginBottom: 8
    textAlign: \center
  year:
    textAlign: \center
  thumbnail:
    width: 53
    height: 81
  listView:
    paddingTop: 20
    backgroundColor: \#F5FCFF

AppRegistry.registerComponent \AwesomeProject, -> AwesomeProject

階層很分明,尤其是在 livescript 中 do 保留字真的非常好用。

comments powered by Disqus