15

我正處於嘗試編寫一些合理的Javascript的早期階段。我想要命名空間基本上我的應用程序名稱下的所有東西,以儘可能避免全局性,但仍然給我一種方式來訪問在該地點聲明的函數。但是,我不想在我的函數定義中超級冗長。如何在Rails 3.1中使用Sprockets編寫DRY,模塊化coffeescript?

我理想中的CoffeeScript會是這樣的:

class @MyApp 
    @myClassMethod = -> 
    console.log 'This is MyApp.myClassMethod()' 

    class @Module1 
    @moduleMethod = -> 
     console.log 'This is MyApp.Module1.moduleMethod()' 

你得到的圖片。這樣我就不必每次都要寫MyApp.Module.submoduleMethod = ->,每次我想正確定義一個名稱空間函數時 - 使用@並在內定義的東西我的類定義使事情更好,更短。

這一切都很順利,直到我想將我的功能分成多個CoffeeScript文件。然後,我真正想要的是這樣的:

// application.js 
class @MyApp 
    //= require 'module1' 
    //= require 'module2' 

// module1.js 
class @Module1 
    @moduleMethod = -> 
    console.log 'This is STILL MyApp.Module1.moduleMethod()' 

它似乎並不像鏈輪可以做到這一點。

是否有一個明智的方法來要求我的CoffeeScript文件在我的容器文件的正確位置?或者另一種方法來編寫使用CoffeeScript,Sprockets和Rails 3.1分成單獨文件的模塊化代碼?

+1

我認爲這個問題需要進一步調查 - 下面的答案不夠好,特別是,由於coffeescript的創建者已經刪除了「簡單模塊」頁面b/c,所以該技術很差。 – dmonopoly

回答

3

我有我的代碼中使用一個模塊的解決方案。

我這樣定義如下

@module "foo", -> 
    @module "bar", -> 
     class @Amazing 
      toString: "ain't it" 

令人驚異的是可用我的模塊,

foo.bar.Amazing 

實施@module幫手的是

window.module = (name, fn)-> 
    if not @[name]? 
    this[name] = {} 
    if not @[name].module? 
    @[name].module = window.module 
    fn.apply(this[name], []) 

這是寫了CoffeeScript的網站上點擊這裏。

https://github.com/jashkenas/coffee-script/wiki/Easy-modules-with-coffeescript

+1

感謝您的鏈接。任何想法如何擴展這個,以便它可以跨多個文件很好地工作? – nfm

+0

它可以在多個文件中工作。這是它的重點。很好的意思是什麼? – bradgonesurfing

+0

我的意思是不必定義每個文件中的所有父模塊。這可能不像我第一次想到的那樣惱人。 – nfm

4

只要保持module1.js原樣,使application.js中是這個樣子:

//= require 'module1' 

class @MyApp 
    ... 

    @Module1 = Module1 

這工作,因爲你做了Module1全球(聲明class @Module1相當於寫@Module1 = class Module1,和@指向window),並且在class @MyApp正文中,@指向類本身。

如果你想Module1它連接後才成爲全球MyApp類的屬性,您可以添加行

delete window.Module1 
+0

好主意!如果我的模塊名稱與頁面上其他腳本中的名稱衝突,那麼仍然會有問題,對不對?我很挑剔,因爲我正在編寫可能會使用書籤注入其他頁面的代碼。 – nfm

+0

啊,在這種情況下,我只需定義一個全局,然後將其他所有內容都附加到它。要做到這一點,請翻轉您的依賴項順序:在application.js中,需要'module1.js',並在'module1.js'中需要'myapp.js',以便首先定義全局的MyApp。然後你可以編寫'class MyApp.Module' ... –

+0

我上面的答案處理名稱衝突問題。使用課堂是好的,但它不像紅寶石,你可以猴子補丁。它會清除以前定義的類。 http://stackoverflow.com/questions/6815957/how-do-you-write-dry-modular-coffeescript-with-sprockets-in-rails-3-1/6826293#6826293繞過這個 – bradgonesurfing

1

下面是模塊化的模式我用與鏈輪管理CoffeeScript的(可與軌道4以及):這個方法的

# utils.js.coffee 

    class Utils 
    constructor: -> 

    foo: -> 
     alert('bar!!!') 

    # private methods should be prefixed with an underscore 
    _privateFoo: -> 
     alert('private methods should not be exposed') 

    instance = new Utils() 

    # only expose the methods you need to. 
    # because this is outside of the class, 
    # you can use coffee's sugar to define on window 

    @utils = foo: instance.foo 

    # otherscript.js.coffee 

    //= require utils 
    class OtherScript 
    constructor: -> 
     @utils.foo()   # alerts bar!!! 
     @utils._privateFoo() # undefined method error 

一個disadavantage是你在窗口暴露你的對象。根據您的需求添加模塊加載器或採用模塊周圍的一些新ES語法可能是一個不錯的選擇。