Rails 5 / JavaScript:仅动态更新已在页面上更新的记录属性

时间:2018-06-05 20:36:39

标签: javascript html ruby-on-rails-5 decorator

我正在关注presenter / decorator模式,其中我有一个单独的包装类,用于添加额外的功能,如格式化属性等...

我的演示者还将属性包装在具有唯一DOM ID引用的span标记中:

<span data-behavior="user_1_full_name">John Smith</span>

这允许我使用JavaScript动态更新属性而不更新整个页面。请注意,我正在使用data-behavior,因为ID and CLASS应该留给CSS样式IMO,它可以避免冲突。

User < ApplicationRecord
  validates :first_name, presence: true
  validates :last_name, presence: true
end

UserPresenter < SimpleDelegator
  def initialize(record, view_context = nil)
    @record = record
    @view_context = view_context
  end

  # Iterate over this to dynamically update
  def attributes_to_update
    [:full_name, :first_name, :last_name].freeze
  end

  # ie, "John Smith"
  def full_name
    text = [@record.first_name, @record.last_name].join(" ")
    attribute_wrapper(:full_name, text)    
  end

  private

  # Wraps attributes in unique data-behavior wrapper:
  # ie: <span data-behavior="user_1_full_name">John Smith</span>
  def attribute_wrapper(attribute, value)
    @view_context.content_tag :span, value, data: { behavior: "#{dom_id(@record)}_#{attribute}".strip }
  end
end

这很有效,我可以使用这些data-behavior属性动态更新属性。

但是,我有一个拥有30多个这些属性的模型。演示者存储要更新的属性数组,因此我可以使用几行代码在js.erb视图文件中更新它们:

# app/views/users/update.js.erb with jQuery
<%= @user_presenter.attributes_to_update.each do |attribute| %>
  $("[data-behavior='user_<%= @user.id %>_<%= attribute %>]").replaceWith("<%=j @user.public_send(attribute) %>");
<% end %>

问题是,当我更新单个字段时,它将更新所有30多个字段。除了使用像React这样的完整前端框架之外,还有一种干净的方法来更新已更改的属性吗?

我很喜欢使用vanilla JS或任何StimulusJS解决方案甚至是小型库,但我并没有尝试在前端编写所有内容。

1 个答案:

答案 0 :(得分:0)

解决方案1 ​​

使用小型虚拟DOM库(例如HyperHTML)。它们是其他几个类似的库,您可以对其进行搜索。我过去使用过HyperHtml,效果很好

https://github.com/WebReflection/hyperHTML

解决方案2 如果您使用的是Stimulus,则可以跟踪每个字段值,并使用Stimulus API`data.set(“ field-name”)将它们存储在data属性中。这是一个字符串,因此如果要存储对象,则需要先对其进行字符串化。如果值已更改,则仅更新字段。 Stilulus文档中的更多信息

https://stimulusjs.org/handbook/managing-state