mirror of
https://github.com/yewstack/yew.git
synced 2025-12-08 21:26:25 +00:00
Fix add a listener to VTag when the listeners is None (#2375)
* Fix add listener and remove unused listener code * Format code
This commit is contained in:
parent
a8f7113d4a
commit
fac220fd64
@ -1,64 +0,0 @@
|
||||
macro_rules! impl_action {
|
||||
($($action:ident(name: $name:literal, event: $type:ident) -> $ret:ty => $convert:expr)*) => {$(
|
||||
/// An abstract implementation of a listener.
|
||||
#[doc(hidden)]
|
||||
pub mod $action {
|
||||
use crate::callback::Callback;
|
||||
#[allow(unused_imports)]
|
||||
use crate::html::{listener::*, IntoPropValue};
|
||||
use crate::virtual_dom::Listener;
|
||||
use gloo::events::{EventListener, EventListenerOptions};
|
||||
use wasm_bindgen::JsValue;
|
||||
use web_sys::{$type as WebSysType, Element, EventTarget};
|
||||
use std::rc::Rc;
|
||||
|
||||
/// A wrapper for a callback which attaches event listeners to elements.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Wrapper {
|
||||
callback: Callback<Event>,
|
||||
}
|
||||
|
||||
impl Wrapper {
|
||||
/// Create a wrapper for an event-typed callback
|
||||
pub fn new(callback: Callback<Event>) -> Self {
|
||||
Wrapper { callback }
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[inline]
|
||||
pub fn __macro_new(callback: impl IntoEventCallback<Event>) -> Option<Rc<dyn Listener>> {
|
||||
let callback = callback.into_event_callback()?;
|
||||
Some(Rc::new(Self::new(callback)))
|
||||
}
|
||||
}
|
||||
|
||||
/// And event type which keeps the returned type.
|
||||
pub type Event = $ret;
|
||||
|
||||
impl Listener for Wrapper {
|
||||
fn kind(&self) -> &'static str {
|
||||
stringify!($action)
|
||||
}
|
||||
|
||||
fn attach(&self, element: &Element) -> EventListener {
|
||||
let this = element.clone();
|
||||
let callback = self.callback.clone();
|
||||
let listener = move |
|
||||
event: &web_sys::Event
|
||||
| {
|
||||
let event: WebSysType = JsValue::from(event).into();
|
||||
callback.emit($convert(&this, event));
|
||||
};
|
||||
// We should only set passive event listeners for `touchstart` and `touchmove`.
|
||||
// See here: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Improving_scrolling_performance_with_passive_listeners
|
||||
if $name == "touchstart" || $name == "touchmove" {
|
||||
EventListener::new(&EventTarget::from(element.clone()), $name, listener)
|
||||
} else {
|
||||
let options = EventListenerOptions::enable_prevent_default();
|
||||
EventListener::new_with_options(&EventTarget::from(element.clone()), $name, options, listener)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)*};
|
||||
}
|
||||
@ -525,7 +525,6 @@ mod tests {
|
||||
use crate::{html, html::TargetCast, AppHandle, Component, Context, Html};
|
||||
use gloo_utils::document;
|
||||
use wasm_bindgen::JsCast;
|
||||
use wasm_bindgen_futures::JsFuture;
|
||||
|
||||
#[derive(Clone)]
|
||||
enum Message {
|
||||
@ -655,37 +654,6 @@ mod tests {
|
||||
assert_count(&el, 2);
|
||||
}
|
||||
|
||||
async fn await_animation_frame() {
|
||||
JsFuture::from(js_sys::Promise::new(&mut |resolve, _| {
|
||||
gloo_utils::window()
|
||||
.request_animation_frame(&resolve)
|
||||
.unwrap();
|
||||
}))
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
async fn assert_async<M: Mixin + 'static>() {
|
||||
let (link, el) = init::<M>("a");
|
||||
|
||||
macro_rules! assert_after_click {
|
||||
($c:expr) => {
|
||||
el.click();
|
||||
await_animation_frame().await;
|
||||
assert_count(&el, $c);
|
||||
};
|
||||
}
|
||||
|
||||
assert_count(&el, 0);
|
||||
|
||||
assert_after_click!(1);
|
||||
|
||||
assert_after_click!(2);
|
||||
|
||||
link.send_message(Message::StopListening);
|
||||
assert_after_click!(2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
async fn non_bubbling_event() {
|
||||
struct NonBubbling;
|
||||
|
||||
@ -434,14 +434,19 @@ impl VTag {
|
||||
/// Add event listener on the [VTag]'s [Element].
|
||||
/// Returns `true` if the listener has been added, `false` otherwise.
|
||||
pub fn add_listener(&mut self, listener: Rc<dyn Listener>) -> bool {
|
||||
if let Listeners::Pending(listeners) = &mut self.listeners {
|
||||
let mut listeners = mem::take(listeners).into_vec();
|
||||
listeners.push(Some(listener));
|
||||
match &mut self.listeners {
|
||||
Listeners::None => {
|
||||
self.set_listeners([Some(listener)].into());
|
||||
true
|
||||
}
|
||||
Listeners::Pending(listeners) => {
|
||||
let mut listeners = mem::take(listeners).into_vec();
|
||||
listeners.push(Some(listener));
|
||||
|
||||
self.set_listeners(listeners.into_boxed_slice());
|
||||
true
|
||||
} else {
|
||||
false
|
||||
self.set_listeners(listeners.into());
|
||||
true
|
||||
}
|
||||
Listeners::Registered(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user