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

3
我是一名前端开发者,目前正在一个大型Ruby on Rails项目团队中工作。该项目不是SPA应用,所有页面渲染都在服务器端完成。
该项目有数十个视图,具有以下逻辑:
if true render this partial else render another partial

我尝试遵循DRY原则,从arkency博客中学到了很多技巧,并尽可能实现可重用组件。

但我感觉缺少像React的componentDidMount之类的东西。

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


你可能会得到很多基于个人观点的答案(因此你的问题可能会被关闭),但我仍然认为这是一个好问题。在Rails中,这是一个非常重要的问题,因为直到最近我从未见过一个良好组织JavaScript的Rails应用程序。我很快就会发布一个答案,但请记住 - 我的答案将完全基于个人观点。 - Justin
2个回答

2
“在Rails的局部视图中编写内联JavaScript(即添加逻辑)可以吗?” 我的回答是否定的。这样做不易于维护,而且很丑陋。 “那么,在可维护的Rails应用程序中编写JavaScript的最佳方法是什么?” 您将得到许多基于观点的答案。实际上,这个问题没有一个“正确的答案”。我的回答既是基于观点的,也远非完美。
话虽如此,我想提出自己的观点。在过去几年中,我见过并构建了大小不同的Rails应用程序(包括10个js文件和100+的应用程序),我对这些应用程序以及我在GitHub上看到的应用程序中JavaScript的组织方式非常不满意。我看到无数个充斥着无组织和不相关代码的JavaScript文件。这对我来说似乎并不像Rails。在过去的几个月中,我一直在尝试找到解决办法,有一个解决方案最接近在Rails应用程序上实现良好组织的JavaScript代码库,并且我认为它符合一些Rails的理念。这种方法的一个缺点是它会污染全局作用域...我很想听听JS开发者如何解决这个问题。

这是Medium文章链接:

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()`的方法。当我使用 Medium帖子中的结构时,我遇到了一个问题,需要在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

您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Sergei Panfilov

0
解决您的问题的一种方法是使用react.rb gem(以及reactive_rails_generator进行安装)。
这将允许您按照您习惯的react样式编写视图。
即使它不是单页应用程序,react.rb也可以作为您的模板语言。如果您有一些交互式页面功能,那么您就可以开始了。
还有一个值得一看的reactive-record gem。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接