Fix event bubbling inside templates after a hot template reload (#2484)

This commit is contained in:
Evan Almloff authored and GitHub committed 2024-06-06 17:10:38 -07:00
1 parent b6cdcb4e7f
commit 5494e38cf8
4 files changed
+101 -68

No files matched your search

+10 -13
View File
@@ -429,7 +429,7 @@ impl VirtualDom {
if let Some(Some(parent_path)) = self.elements.get(element.0).copied() {
if bubbles {
self.handle_bubbling_event(Some(parent_path), name, Event::new(data, bubbles));
self.handle_bubbling_event(parent_path, name, Event::new(data, bubbles));
} else {
self.handle_non_bubbling_event(parent_path, name, Event::new(data, bubbles));
}
@@ -799,14 +799,10 @@ impl VirtualDom {
level = "trace",
name = "VirtualDom::handle_bubbling_event"
)]
fn handle_bubbling_event(
&mut self,
mut parent: Option<ElementRef>,
name: &str,
uievent: Event<dyn Any>,
) {
fn handle_bubbling_event(&mut self, parent: ElementRef, name: &str, uievent: Event<dyn Any>) {
// If the event bubbles, we traverse through the tree until we find the target element.
// Loop through each dynamic attribute (in a depth first order) in this template before moving up to the template's parent.
let mut parent = Some(parent);
while let Some(path) = parent {
let mut listeners = vec![];
@@ -815,13 +811,13 @@ impl VirtualDom {
let target_path = path.path;
// Accumulate listeners into the listener list bottom to top
for (idx, attrs) in el_ref.dynamic_attrs.iter().enumerate() {
let this_path = node_template.attr_paths[idx];
for (idx, this_path) in node_template.breadth_first_attribute_paths() {
let attrs = &*el_ref.dynamic_attrs[idx];
for attr in attrs.iter() {
// Remove the "on" prefix if it exists, TODO, we should remove this and settle on one
if attr.name.trim_start_matches("on") == name
&& target_path.is_decendant(&this_path)
&& target_path.is_decendant(this_path)
{
listeners.push(&attr.value);
@@ -842,6 +838,7 @@ impl VirtualDom {
"Calling {} listeners",
listeners.len()
);
tracing::info!("Listeners: {:?}", listeners);
for listener in listeners.into_iter().rev() {
if let AttributeValue::Listener(listener) = listener {
self.runtime.rendering.set(false);
@@ -870,10 +867,10 @@ impl VirtualDom {
let node_template = el_ref.template.get();
let target_path = node.path;
for (idx, attr) in el_ref.dynamic_attrs.iter().enumerate() {
let this_path = node_template.attr_paths[idx];
for (idx, this_path) in node_template.breadth_first_attribute_paths() {
let attrs = &*el_ref.dynamic_attrs[idx];
for attr in attr.iter() {
for attr in attrs.iter() {
// Remove the "on" prefix if it exists, TODO, we should remove this and settle on one
// Only call the listener if this is the exact target element.
if attr.name.trim_start_matches("on") == name && target_path == this_path {