我遵循演示者/装饰器模式,其中我有一个单独的包装器类用于添加额外功能(如格式化属性等)的记录...
我的演示者还将属性包装在 span
中具有唯一 DOM ID 引用的标记:
<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
的 JavaScript 动态更新属性属性。
但是,我有一个模型具有 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 解决方案甚至小型库,但我不想在前端编写所有内容。
最佳答案
解决方案一
使用小型虚拟 DOM 库,例如 HyperHTML。它们是其他几个这样的库,你可以谷歌它们。我过去使用过 HyperHtml,效果很好
https://github.com/WebReflection/hyperHTML
解决方案 2 如果您正在使用 Stimulus,您可以跟踪每个字段值并使用 Stimulus API `data.set("field-name") 将它们存储在数据属性中。它是一个字符串,所以如果你想存储一个对象,你需要先将它字符串化。然后仅在值已更改时更新字段。 Stilulus 文档中的更多信息
关于javascript - 导轨 5/JavaScript : dynamically update only record attributes that have updated on page,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50708555/