Rails中前端的最佳实践是什么?

时间:2016-04-07 15:07:36

标签: javascript ruby-on-rails

我是一名前端开发人员,目前正在一个关于Ruby on Rails项目的团队中工作。这不是SPA。所有页面呈现都在服务器端完成。

Project有几十个像

这样的逻辑视图
if true render this partial else render another partial

我尝试遵循DRY原则,我从arkency blog学到了很多东西,并尝试尽可能多地实现可重复使用的组件。

但是我觉得缺少来自React的componentDidMount之类的东西。

所以我的问题是:在rails部分中编写内联javascript(即添加逻辑)是否可以? 为可维护的Rails应用程序编写Javascript的最佳方法是什么?

2 个答案:

答案 0 :(得分:2)

  

可以在rails部分中编写内联javascript(即添加逻辑)吗?

  • 我的回答是否定的。它不可维护而且很难看。
  

为可维护的Rails应用程序编写Javascript的最佳方法是什么?

  • 见下文

您将获得大量基于意见的答案。这个问题确实没有真正的答案。我的回答是1)以意见为基础,2)没有近乎完美的地方。

话虽如此,我想提出自己的看法。在过去几年里,我已经看到并构建了大型和小型Rails应用程序(10个js文件和100多个应用程序的应用程序),我对这些应用程序中的JavaScript组织以及我见过的应用程序非常不满意穿过GitHub。我已经看到无数的JavaScript文件充满了无组织和无关联的代码。这似乎对我来说不像Rails。在过去的几个月里,我一直在努力寻找解决方案,我发现有一个解决方案可以在Rails应用程序上最接近组织良好的JavaScript代码库。而且我认为一些Rails理想也是如此。这种方法的一个缺点是它在全球范围内徘徊......我很乐意从JS开发人员那里了解如何解决这个问题。

这是Medium post:

https://medium.com/@cblavier/rails-with-no-js-framework-26d2d1646cd#.36zis335e

我对此做了一些调整,因为有时您需要共享代码,例如,为用户提供共享表单的代码。但是,我想赞美@cblavier。所以请花点时间阅读他的帖子,因为它有一个很好的信息,我不会在下面详细介绍。

要求:Coffeescript,Turbolinks和jQuery

# app/helpers/application_helper.rb

def js_class_name
  action = case action_name
    when 'create' then 'New'
    when 'update' then 'Edit'
    else action_name
  end.camelize

  "Views.#{controller_name.camelize}.#{action}View"
end 

对于上面的帮助程序,如果您的应用程序具有命名空间控制器,则需要考虑命名空间控制器。这应该相当容易。我认为以下内容可以解决问题。

"Views.#{controller_path.camelize.gsub('::', '.')}.#{action}View"

好的,现在您要将其添加到布局中的<body>标记。

<body data-class-name="<%= js_class_name %>">

javascript的时间!

# initializer.coffee
pageLoad = ->
  className = $('body').attr('data-class-name')
  initializePage(className)
  initializePageBase(className)

initializePage = (className) ->
  window.applicationView = try
    eval("new #{className}()")
  catch error
    new Views.ApplicationView()

  window.applicationView.render()

initializePageBase = (className) ->
  modules = className.split('.')
  modules.splice(modules.length - 1, 1)

  window.baseView = try
    eval("new #{modules.join('.')}.BaseView")

  window.baseView.render() unless window.baseView is undefined

$(document).on 'turbolinks:load', pageLoad # turbolinks:load is master branch of turbolinks, if you are using older version, it's page:load
$(document).on 'page:before-change', ->
  window.applicationView.cleanup()
  true
$(document).on 'page:restore', ->
  window.applicationView.cleanup()
  pageLoad()
  true
# app/assets/javascripts/views/application_view.coffee
window.Views ||= {}

class Views.ApplicationView
  render: ->
    # pretty much global JS code can be initialized here. It's nice
    # to keep the render() method clean though. Like this:
    @setupElements()

  setupElements: ->
    $('[data-toggle=tooltip]').tooltip() # just an example

  cleanup: ->

现在您已经进行了这些设置,现在是时候开始添加页面JavaScript了。这只是页面的一个示例。 users_controller#show

Views.Users ||= {}

class Views.Users.ShowView extends Views.ApplicationView
  constructor: ->
    # find and cache DOM objects, etc
    # ex:
    @someButton = $('[data-behavior=expand-user-info]')

  render: ->
    super() # this is important. It calls render() on ApplicationView

    # example stuff
    @bindEventListeners()

   bindEventListeners: ->
     t = this

     @someButton.on 'click', ->
       t.expandUserInfo()

  expandUserInfo: ->
    alert('woohoo!')

  cleanup: ->
    super()

如果您之前注意到,我们在initializer.coffee方法中调用了一个方法initializePageBase()。当我使用结构from that Medium post时,遇到了editnew视图中需要相同javascript的问题。那initializePageBase()是解决问题的第一步。它将查找BaseView类。这是一个例子:

# app/assets/javascripts/views/users/base_view.coffee
Views.Users ||= {}

class Views.Users.BaseView # you don't need to extend ApplicationView here, because we are already initializing it.
  render: ->
    # code

答案 1 :(得分:0)

解决问题的一种方法是使用react.rb gem(和reactive_rails_generator进行安装)

这将允许您以您习惯的反应方式编写视图。

尽管它不是单页应用程序react.rb可以简单地作为你的模板语言。如果你有一些互动页面功能,那么你就可以去了。

还有一个反应记录宝石可能值得研究。