Rails、CoffeeScript- 使用class进行封装以进行命名空间管理

过程

    • グローバルで変数名が衝突しないよう、ネームスペース・モジュール管理をやるべきらしい。

 

    • JSは多用しないので、可能であればRailsサイドで解決したい。

 

    今後は意識して実践していきたいのでメモ。

方法

在进行调查时,发现有很多种方法,但是我喜欢这种方法。

创建一个或多个用于命名空间的目录。

/javascripts
    /namespace    # ネームスペース用のディレクトリー
        base.coffee
        charts.coffee
        moving_items.coffee
        [..]
    application.js
    namespace.js  # ネームスペース設定ファイル

请将命名空间加载到资产管道中

//= require jquery
//= require jquery_ujs
//= require jquery.turbolinks
//= require bootstrap
//= require turbolinks
//...
//= require namespace
//= require ./namespace/base
//= require_tree ./namespace

在base文件中准备命名空间对象。

@Namespace = {}

# $(document).on "ready page:load", ->
#  $('a[href^="/documents/"]').attr('target', '_blank')

将JS代码包装在命名空间下的类中

在等待实例化之前,类内的代码将会被暂时搁置。

构造函数返回某个值的例子。

# Chart.js configuration

Chart.defaults.global.tooltipEvents = ["mousemove", "touchstart", "touchmove"]
Chart.defaults.global.scaleLabel    = "<%=value%>cu.ft"

class @Components.ChartComponent

  constructor: (chartType)->
    return @createClass(chartType)

  createClass: (chartType) ->

    React.createClass
      displayName: "#{chartType}Chart"
      propTypes:
        name:    React.PropTypes.string
        data:    React.PropTypes.oneOfType([React.PropTypes.array, React.PropTypes.object])
        height:  React.PropTypes.number
        width:   React.PropTypes.number
        options: React.PropTypes.object

      getInitialState: ->
        chartInstance: null

      render: ->
        React.DOM.canvas
          ref:   @props.name
          style: { height: @props.height, width: @props.width }

      componentDidMount: ->
        @initializeChart()

      componentWillUnmount: ->
        @state.chartInstance.destroy() if @state.chartInstance

      initializeChart: ->
        canvas = React.findDOMNode(@refs[@props.name])
        ctx    = canvas.getContext("2d")
        chart  = new Chart(ctx)[chartType](@props.data)
        @setState.chartInstance = chart

以下是使用构造函数注册事件监听器的例子。

# moving_items/new, moving_items/edit

class @Namespace.MovingItems

  constructor: ->

    setVolume = (volume) -> $("#moving_item_volume").val(volume)
    setSlider = (volume) -> $("#volume_slider").val(volume)

    # Slider

    document.getElementById('volume_slider').addEventListener 'change', ->
      setVolume(document.getElementById('volume_slider').value)

    # AutoComplete

    $('#moving_item_name').autocomplete
      source: Object.keys( $('#suggestions').data('items') )
      select: (e, ui) =>
        itemVolume = $('#suggestions').data('items')[ui.item.value]
        setVolume(itemVolume)
        setSlider(itemVolume)

    $('#moving_item_room').autocomplete
      source: $('#suggestions').data('rooms')

    $('#moving_item_category').autocomplete
      source: $('#suggestions').data('categories')

使用HAML的:coffee滤镜来调用并实例化JS代码。

:coffee
  window.BarChartComponent = new Namespace.ChartComponent("Bar")
  window.PieChartComponent = new Namespace.ChartComponent("Pie")

.panel.panel-blue
  .panel-heading
    /...
  - if @total_volume > 0
    .panel-body
      .row
        .col-sm-6
          = react_component 'BarChartComponent', { name: "MovingBarChart",
            data: @dataForBarChart, height: 200, width:  400 }
        .col-sm-6
          = react_component 'PieChartComponent', { name: "MovingPieChart",
            data: @dataForPieChart, height: 200, width:  200 }

在(:javascript)中,也可以使用content_for(:javascript)和yield(:javascript)来实现相同的效果。

!!!
%html
  %head
    /...
  %body
    = yield               # ページコンテンツ
    /...
    = yield(:javascript)  # 必要なJSコードを生成する
- content_for(:javascript) do
  :coffeescript
    jQuery ->
      window.BarChartComponent = new Namespace.ChartComponent("Bar")
      window.PieChartComponent = new Namespace.ChartComponent("Pie")
/...

信息

    • Essential JavaScript Namespacing Patterns

 

    • JavaScript Namespacing with the Rails Asset Pipeline

 

    • Write maintainable JavaScript/CoffeeScript in Rails

 

    CoffeeScriptのclassをグローバルに定義する。
广告
将在 10 秒后关闭
bannerAds