我正在关注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解决方案甚至是小型库,但我并没有尝试在前端编写所有内容。
答案 0 :(得分:0)
解决方案1
使用小型虚拟DOM库(例如HyperHTML)。它们是其他几个类似的库,您可以对其进行搜索。我过去使用过HyperHtml,效果很好
https://github.com/WebReflection/hyperHTML
解决方案2 如果您使用的是Stimulus,则可以跟踪每个字段值,并使用Stimulus API`data.set(“ field-name”)将它们存储在data属性中。这是一个字符串,因此如果要存储对象,则需要先对其进行字符串化。如果值已更改,则仅更新字段。 Stilulus文档中的更多信息