Как вы пишете СУХОЙ, модульный coffeescript с помощью Sprockets в Rails 3.1?
Я нахожусь на ранних стадиях попыток написать какой-нибудь разумный Javascript. Я хочу, чтобы в основном все пространство имен содержалось под именем моего приложения, чтобы максимально избежать глобальных переменных, но все же дать мне возможность доступа к функциям, объявленным повсеместно. Однако я не хочу быть супер многословным в своих определениях функций.
Мой идеальный 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?
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
Просто сохраните module1.js как есть и заставьте application.js выглядеть примерно так:
//= require 'module1'
class @MyApp
...
@Module1 = Module1
Это будет работать, потому что вы сделали Module1
глобальный (декларирующий class @Module1
эквивалентно письму @Module1 = class Module1
, а также @
указывает на window
в этом контексте) и в рамках class @MyApp
тело, @
указывает на сам класс.
Если ты хочешь Module1
быть только собственностью глобального MyApp
класс после того, как он прикреплен, вы можете добавить строку
delete window.Module1
Вот модульный шаблон, который я использую для управления coffeescript с помощью звездочек (также работает с Rails 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
Одним из недостатков этого подхода является то, что вы выставляете свои объекты на окне. Добавление загрузчика модулей или принятие нового синтаксиса es вокруг модулей может быть хорошей альтернативой в зависимости от ваших потребностей.