如何在 Rails 3.1 中使用 Sprockets 编写 DRY、模块化的 CoffeeScript?

发布于 2024-11-26 03:40:01 字数 917 浏览 1 评论 0原文

我正处于尝试编写一些合理的 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 编写分成单独文件的模块化代码的另一种方法?

I'm in the early stages of trying to write some sensible Javascript. I want to namespace basically everything under the name of my application to avoid globals as much as possible, but still give me a way to access functions declared around the place. However, I don't want to be super verbose in my function definitions.

My ideal CoffeeScript would be something like this:

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

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

You get the picture. This way I avoid having to write MyApp.Module.submoduleMethod = -> every time I want to define a namespaced function properly - using @ and defining things within my class definition keeps things nice and short.

This is all going well until I want to split my functionality up into multiple CoffeeScript files. Then what I really want is something like this:

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

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

It doesn't seem like Sprockets can do this.

Is there a sensible way to require my CoffeeScript files in the right place in my container files? Or another way to approach writing modular code that is divided into separate files using CoffeeScript, Sprockets and Rails 3.1?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

暗喜 2024-12-03 03:40:01

只需保持 module1.js 不变,并使 application.js 看起来像这样:

//= require 'module1'

class @MyApp
  ...

  @Module1 = Module1

这将起作用,因为您已将 Module1 设为全局(声明 class @Module1 等效)编写 @Module1 = class Module1,并且 @ 指向该上下文中的 window),并且在 class @MyApp正文,<代码>@指向类本身。

如果您希望 Module1 在附加后成为全局 MyApp 类的属性,您可以添加以下行

delete window.Module1

Simply keep module1.js as-is and make application.js look something like this:

//= require 'module1'

class @MyApp
  ...

  @Module1 = Module1

This will work because you've made Module1 a global (declaring class @Module1 is equivalent to writing @Module1 = class Module1, and @ points to window in that context), and within the class @MyApp body, @ points to the class itself.

If you want Module1 to only be a property of the global MyApp class after it's attached, you could add the line

delete window.Module1
っ〆星空下的拥抱 2024-12-03 03:40:01

我有一个在代码中使用的模块解决方案。

我定义了我的模块,如下所示。 令人惊奇的是

@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

I have a module solution that I use in my code.

I define my modules like below

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

Amazing is available as

foo.bar.Amazing

implementation of the @module helper is

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

It's written up on the coffeescript website here.

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

高冷爸爸 2024-12-03 03:40:01

下面是我使用 sprocket 管理 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 语法可能是一个不错的选择。

Here's the modular pattern I use for managing coffeescript with sprockets (works with Rails 4 as well):

  # 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

One disadavantage of this approach is that you are exposing your objects on window. Adding a module loader or adopting some of the new es syntax around modules could be a nice alternative depending on your needs.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文