使用 hyperstack.org 框架,如何在更改正在渲染的模型时减少渲染周期?
当将正在渲染的模型传递给改变该模型的组件时,渲染该模型的所有组件都会在任何突变时重新渲染。这很好,除非突变是每次按键,因为这意味着所有组件都会在每次按键时重新渲染。
例如,如果我们有这张表:
class UserIndex < HyperComponent
render(DIV) do
puts "UserIndex render"
BridgeAppBar()
UserDialog(user: User.new)
Table do
TableHead do
TableRow do
TableCell { 'Name' }
TableCell { 'Gender' }
TableCell { 'Edit' }
end
end
TableBody do
user_rows
end
end
end
def user_rows
User.each do |user|
TableRow do
TableCell { "#{user.first_name} #{user.last_name}" }
TableCell { user.is_female ? 'Female' : 'Male' }
TableCell { UserDialog(user: user) }
end
end
end
end
而这个组件(用于编辑和新建):
class UserDialog < HyperComponent
param :user
before_mount do
@open = false
end
render do
puts "UserDialog render"
if @open
render_dialog
else
edit_or_new_button.on(:click) { mutate @open = true }
end
end
def render_dialog
Dialog(open: @open, fullWidth: false) do
DialogTitle do
'User'
end
DialogContent do
content
error_messages if @User.errors.any?
end
DialogActions do
actions
end
end
end
def edit_or_new_button
if @User.new?
Fab(size: :small, color: :primary) { Icon { 'add' } }
else
Fab(size: :small, color: :secondary) { Icon { 'settings' } }
end
end
def content
FormGroup(row: true) do
TextField(label: 'First Name', defaultValue: @User.first_name.to_s).on(:change) do |e|
@User.first_name = e.target.value
end
TextField(label: 'Last Name', defaultValue: @User.last_name.to_s).on(:change) do |e|
@User.last_name = e.target.value
end
end
BR()
FormLabel(component: 'legend') { 'Gender' }
RadioGroup(row: true) do
FormControlLabel(label: 'Male',
control: Radio(value: false, checked: !@User.is_female).as_node.to_n)
FormControlLabel(label: 'Female',
control: Radio(value: true, checked: @User.is_female).as_node.to_n)
end.on(:change) do |e|
@User.is_female = e.target.value
end
end
def actions
Button { 'Cancel' }.on(:click) { cancel }
if @User.changed? && validate_content
Button(color: :primary, variant: :contained, disabled: (@User.saving? ? true : false)) do
'Save'
end.on(:click) { save }
end
end
def save
@User.save(validate: true).then do |result|
mutate @open = false if result[:success]
end
end
def cancel
@User.revert
mutate @open = false
end
def error_messages
@User.errors.full_messages.each do |message|
Typography(variant: :h6, color: :secondary) { message }
end
end
def validate_content
return false if @User.first_name.to_s.empty?
return false if @User.last_name.to_s.empty?
return false if @User.is_female.nil?
true
end
end
基础表(来自第一个代码示例)在每次按键时重新呈现,原因如下:
TextField(label: 'First Name', defaultValue: @User.first_name.to_s)
.on(:change) do |e|
@User.first_name = e.target.value
end
由于重新渲染的数量,这导致打字看起来很慢。
我应该为每个字段保留一个本地状态变量,然后只在保存时改变模型字段吗?