React: Unterstützen Sie passive Ereignislistener

Erstellt am 7. Apr. 2016  ·  62Kommentare  ·  Quelle: facebook/react

https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md

Es wäre gut, wenn standardmäßig alles passiv wäre und sich nur bei Bedarf für aktiv entscheiden würde. ZB können Sie Texteingabeereignisse abhören, aber nur verhindernDefault oder kontrolliertes Verhalten verwenden, wenn Sie aktive Listener haben.

Ebenso könnten wir dies mit dem Threading-Modell von React Native vereinheitlichen. Zum Beispiel könnten wir dort den UI-Thread synchron blockieren, wenn aktive Listener vorhanden sind, wie z. B. die Handhabung von Tastenanschlägen.

cc @vjeux @ide

DOM React Core Team Big Picture Feature Request

Hilfreichster Kommentar

Ich habe gerade in Chrome eine Warnung zur Behandlung des Wheel-Events angezeigt, die optimiert werden könnte, wenn sie als passiver Event-Handler registriert würde. Es wäre also nett, dies in React zu haben!

Alle 62 Kommentare

Dies ist in Chrome 51 gelandet. Gibt es einen aktualisierten Plan, um dies in React zu unterstützen? :Ö

Wie ist dies möglich, wenn React nur einen Ereignis-Listener für das Dokument hat und dann an andere delegiert?
@sebmarkbage

Wie ist der aktuelle Problemstatus bei passiven Ereignissen?

Ich habe gerade in Chrome eine Warnung zur Behandlung des Wheel-Events angezeigt, die optimiert werden könnte, wenn sie als passiver Event-Handler registriert würde. Es wäre also nett, dies in React zu haben!

Sie werden auch beliebige Optionen behandeln wollen, wie zum Beispiel once das bereits nachts in Firefox gelandet ist: https://twitter.com/mozhacks/status/758763803991474176. Vollständige Liste: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener

FWIW, Facebook hört auf aktive Radereignisse, um das äußere Scrollen zu blockieren, wenn Seitenleisten oder Chatfenster gescrollt werden. Ohne sie können wir die Benutzeroberfläche nicht implementieren. Wir möchten dies immer noch als Option unterstützen, aber der Problemraum ist noch unvollständig, sodass sich möglicherweise alternative Lösungen für dieses Problem entwickeln, die keine passiven Ereignislistener beinhalten. Es ist also immer noch ein aktiver Gestaltungsraum.

Es ist wichtig, sowohl aktive Hörer zu behalten als auch passive Hörer hinzuzufügen.
Bei Desktop-Anwendungen sieht man keinen Unterschied, aber bei mobilen Apps geben passive Scroll-Listener einen großen Geschwindigkeitsschub.

Kleiner Vorschlag:

<SomeElement
  onScroll={this.onScrollThatCallsPreventDefault}
  onScrollPassive={this.onScrollThatJustListens}
  ...this.props
/>

@romulof ja, so registrierst du auch Ereignisse in der Capture-Phase

<SomeElement
  onClick={this.onClick}
  onClickCapture={this.onClickCapture}
  onScrollPassive={this.onScrollPassive}
/>

Ich kann mir also vorstellen, dass dies die richtige API ist, um auch passive Ereignisse zu unterstützen.

Randnotiz: Eine knifflige Frage ist: Wie würden Sie passive Ereignisse für die Erfassungsphase registrieren? Ich nehme an, dass dies aufgrund der Natur passiver Ereignisse nicht möglich ist. Da sie event.preventDefault() nicht einmal anrufen dürfen, ist dies wahrscheinlich kein Problem.

@radubrehar , onScrollCapturePassive sieht aus wie die ganze Bibel im Kamelkasten .

:) Dies ist nicht der Fall, da es in der Capture-Phase keine passiven Ereignisse gibt.

Natürlich macht es keinen Sinn, aber darauf würde ich mich nicht verlassen. Es gibt auch andere Arten von Ereignisbindungen, z. B. once .

Noch ein Vorschlag:

<SomeElement
  onScroll={this.onScrollThatCallsPreventDefault}
/>
<SomePassiveElement
  onScroll={{
    passive: true,
    capture: true,
    handler: this.onScrollThatJustListens,
  }}
/>

Auf diese Weise müsste React erkennen, ob der Ereignishandler eine Funktion (normale Bindung) oder ein Objekt ist, das Bindungsoptionen und die Handlerfunktion enthält.

Ich denke, der Objektansatz mit Optionen ist sinnvoller als onFooPassive , da es andere Optionen gibt, die möglicherweise benötigt werden. In Kombination mit dem Vorschlag von @sebmarkbage , dass Ereignisse standardmäßig passiv sein sollten, wäre dies wahrscheinlich nicht zu umständlich.

Ein anderer Ansatz, der mir in den Sinn kommt, besteht darin, dem Ereignishandler Eigenschaften zuzuordnen, die es ihnen ermöglichen, den passiven Modus zu deaktivieren (oder andere Optionen umzuschalten). Etwas wie das:

class Foo extends React.Component {
  constructor() {
    this.handleScroll = this.handleScroll.bind(this);
    this.handleScroll.passive = false;
  }

  handleScroll() {
    ...
  }

  render() {
    return <div onScroll={this.handleScroll} />;
  }
}

Theoretisch würde dies mit Dekorateuren ziemlich gut funktionieren, sobald sie gelandet sind.

Wenn ich etwas genauer darüber nachdenke, denke ich, dass es besser wäre, der Funktion eine Ereignisoptionseigenschaft hinzuzufügen, anstatt einzelne Optionen. Dies würde es React ermöglichen, sich nur um eine Eigenschaft anstatt möglicherweise um viele zu kümmern. Also, um mein Beispiel oben anzupassen:

class Foo extends React.Component {
  constructor() {
    this.handleScroll = this.handleScroll.bind(this);
    this.handleScroll.options = { passive: false };
  }

  handleScroll() {
    ...
  }

  render() {
    return <div onScroll={this.handleScroll} />;
  }
}

Ein weiterer Gedanke, der mir in den Sinn kam, ist, wie dies aussehen könnte, wenn wir die JSX-Syntax so

return <div onScroll={this.handleScroll, { passive: false }} />;

Ich habe auch darüber nachgedacht, ob Ereignisse standardmäßig passiv sein sollen oder nicht, und ich bin ein bisschen am Zaun. Einerseits wäre dies sicherlich für Ereignisse wie Scroll-Handler schön, aber ich befürchte, dass es für viele Klick-Handler zu viel Turbulenzen und unerwartetes Verhalten verursachen würde. Wir könnten es so machen, dass einige Events standardmäßig passiv sind und andere nicht, aber das würde die Leute wahrscheinlich nur verwirren, also wahrscheinlich keine gute Idee.

Dieser Weg ist dem, den ich zuvor vorgeschlagen habe, ziemlich ähnlich, ohne die JSX-Syntax zu ändern.

return <div onScroll={{ handler: this.handleScroll, passive: true }} />;

Und die Dokumentation wäre einfach:

div.propTypes = {
  ...
  onScroll: React.PropTypes.oneOf([
    React.PropTypes.func,
    React.PropTypes.shape({
      handler: React.PropTypes.func.isRequired,
      capture: React.PropTypes.bool,
      passive: React.PropTypes.bool,
      once: React.PropTypes.bool,
    }),
};

Sind Reaktionsereignisse standardmäßig passiv? Zumindest bei Touch-Events scheint es so zu sein. Ich kann preventDefault ausführen, wenn ich auf Vanilla-Ereignis-Listener auf Dokumentebene zurückgreife.

@joshjg React-Handler werden "synthetische Ereignisse" übergeben, die wie native Ereignisse sind, aber anders. Übrigens sollte jemand mit mehr Wissen korrigieren, was ich sagen werde, da ich den Code, der dies tut, nicht wirklich gelesen habe.

Ich bin mit den Implementierungsdetails nicht sehr vertraut, aber ich weiß, dass preventDefault zumindest _solange funktioniert, wie die Handler, die Sie verhindern, auch React-Ereignishandler sind_. Das ist jedenfalls meine Erfahrung.

Mit stopPropagation hast du eher Pech (zB hast du einen document Klick-Listener, der nicht mit React verbunden werden kann, und du willst vermeiden, dass du blubberst, wenn du hineinklickst ein bestimmtes Element). In diesem Fall können Sie Folgendes verwenden:

function stopPropagation (e) {
  e.stopPropagation();
  e.nativeEvent.stopImmediatePropagation();
}

[[MDN](https://developer.mozilla.org/en-US/docs/Web/API/Event/stopImmediatePropagation)]

Dies ist etwas vom Hauptthema abgekommen, aber die kurze Antwort ist, dass React keine passiven Ereignisse verwendet, sie werden nur manchmal in einer seltsamen Reihenfolge behandelt.

@joshjg @benwiley4000 @gaearon Vor kurzem hat das Chrome-Team seine Herangehensweise an Touch-Events auf Dokumentebene geändert und sie standardmäßig passiv gemacht. Und da React Ereignisse auf Dokumentebene anhängt, erhalten Sie dieses neue Verhalten.

Siehe https://www.chromestatus.com/features/5093566007214080

Dies hat indirekt das Verhalten von React geändert - ich nehme an, React erwähnt passive: false beim Anhängen von Ereignissen nicht explizit - daher die Verhaltensänderung.

Ich habe das auch gerade getroffen - Sie müssen also Touch-Ereignisse von Hand registrieren, mit addEventListener

Beachten Sie, dass die standardmäßige passive Chrome-Intervention nur für touchstart und touchmove , nicht für wheel . Ein wheel Ereignis ohne explizites {passive: true} erzwingt also immer noch synchrones Scrollen, für das Scrollen mit dem Mausrad und dem Trackpad mit zwei Fingern. (Ich habe hier einen Blogbeitrag über einige der Feinheiten geschrieben.)

Außerdem haben wir (das Edge-Team) nicht die Absicht, dieselbe Intervention zu implementieren. Wenn wir also passive Ereignis-Listener ausliefern, möchten Sie immer noch explizit {passive: true} angeben.

Zu Ihrer Information, ich habe angefangen, den passiven: false-Pfad zu durchlaufen, um zu verhindern, dass der Körper auf dem Handy scrollt, wenn es ein scrollendes Div gibt, aber es ist ein wenig schwer, PreventDefault() zu verwenden, um das Scrollen zu blockieren. Ich könnte den Handler hinzufügen und entfernen, je nachdem, ob das div vorhanden ist, oder auf einen body.height = 100%-Ansatz zurückgreifen. Die Korrektur der Körperhöhe fühlt sich ein wenig hackig an, aber dann bräuchte ich kein passiv: überhaupt falsch.

Mein Anwendungsfall ist, dass ich die Methode event.preventDefault() verwenden möchte, um das Scrollen des Containers zu verhindern, wenn der Benutzer ein Element hineinzieht.

Dazu muss ich den Ereignis-Listener als nicht-passiv (passiv: false) registrieren.
Da Browser auf passiv umschalten: Standardmäßig wahr, ich möchte das Gegenteil tun können

Leider kann ich den Stil touch-action: none; da er nach dem Start der Berührung angewendet wird und wahrscheinlich deshalb keine Wirkung hat.

Es wird in der Tat sehr bald ein Problem sein, ich bin überrascht, dass in zwei Jahren keine Lösung gefunden wurde. Und das manuelle Erstellen von Ereignis-Listenern ist ein Anti-Pattern in React.

Und wenn es bahnbrechende Veränderungen schafft, dann soll es so sein. Vielleicht fehlt mir aber ein Teil der Geschichte.

Ich mag die neue Event-Listener-Signatur, die von @romulof in https://github.com/facebook/react/issues/6436#issuecomment -254331351 vorgeschlagen wurde.
Neben der Behebung des hier beschriebenen Problems wäre es möglich, andere EventListenerOptions wie once anzugeben

Ich bin gerade auf dieses Problem gestoßen. Ich habe eine Leinwand, auf der der Benutzer zeichnen kann. Beim Zeichnen auf Android wird manchmal "zum Aktualisieren gezogen", anstatt einen Pinselstrich zu machen. Dies zeigt, dass es sich um ein reales Problem handelt. Ich werde onTouch{Start,Move,End} vorerst vermeiden und manuell addEventListener als Workaround verwenden.

Der von @romulof vorgeschlagene Ansatz

@bobvanderlinden Das Hinzufügen von touch-action: none; zu Ihrem Canvas-Stil sollte für Sie funktionieren, es glänzt wirklich für diesen Anwendungsfall. Auch die anderen möglichen Werte können sehr praktisch sein.

Wie @piotr-cz jedoch betonte, löst touch-action dieses Problem mit passiven Ereignissen nicht allgemein als Ganzes. Ich stoße auch auf das gleiche Problem, bei dem verhindert wird, dass ein Container beim Ziehen eines untergeordneten Elements scrollt. Alle Problemumgehungen sind ziemlich hackig und fügen technische Schulden hinzu.

Unglücklicherweise kann die Anwesenheit eines nicht-passiven Listeners einen erheblichen Jank verursachen, selbst wenn keine Userland-Handler tatsächlich daran angeschlossen sind. Chrome informiert Sie verbose Protokollebenen [Violation] Handling of 'wheel' input event was delayed for 194 ms due to main thread being busy. Consider marking event handler as 'passive' to make the page more responsive. (dies ist der Top-Level-Handler, der von https://github.com/facebook/react/blob/92b7b172cce9958b846844f0b46fd7bbd8c5140d/packages/ hinzugefügt wurde. react-dom/src/events/ReactDOMEventListener.js#L155)

@romulof @lencioni @radubrehar Wissen Sie, dass das passive Flag nicht für die Verwendung auf Scroll-Ereignis-Listenern gedacht ist? Es sollte bei Ereignissen wie touchmove usw. verwendet werden, um die Scrollleistung des Browsers nicht zu beeinträchtigen. Deine Beispiele verwirren mich sehr.

Das Festlegen von passiv ist für das grundlegende Scroll-Ereignis nicht wichtig, da es nicht abgebrochen werden kann, sodass sein Listener das Seitenrendering sowieso nicht blockieren kann.

Quelle: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Improving_scrolling_performance_with_passive_listeners

Zusätzliche Informationen: https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md

Ja, das ist mir jetzt bewusst. Ich war falsch informiert, als ich meine vorhin geschrieben habe
Kommentare. Danke fürs klarstellen!

Am Mi, 06.12.2017, 08:25 Uhr Martin Hofmann [email protected]
schrieb:

@romulof https://github.com/romulof @lencioni
https://github.com/lencioni @radubrehar https://github.com/radubrehar
Ist Ihnen bewusst, dass das passive Flag nicht für die Verwendung auf
Ereignislistener scrollen? Es sollte bei Events wie touchmove etc. verwendet werden.
um die Scrollleistung des Browsers nicht zu beeinträchtigen. Ihre Beispiele
sind für mich sehr verwirrend.

Die Einstellung passiv ist für das grundlegende Scroll-Ereignis nicht wichtig, da dies nicht möglich ist
abgebrochen werden, sodass sein Listener das Rendern der Seite sowieso nicht blockieren kann.

Quelle:
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Improving_scrolling_performance_with_passive_listeners

Zusätzliche Information:
https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md


Sie erhalten dies, weil Sie erwähnt wurden.

Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/facebook/react/issues/6436#issuecomment-349691618 ,
oder den Thread stumm schalten
https://github.com/notifications/unsubscribe-auth/AAL7zgbNCpHNui-TX7r2FYdhVxZfdBX8ks5s9r_4gaJpZM4ICWsW
.

@el-moalo-loco, ich bin mir ziemlich sicher, dass ich auf der Google Developers-Website einige Dokumentation über die Verwendung passiver Listener für Scroll-Ereignisse gelesen habe, um die Leistung zu verbessern. Ich muss mich falsch verstanden haben oder irgendetwas hat sich auf dem Weg geändert. Trotzdem vielen Dank für die Aufklärung!

@romulof @lencioni @el-moalo-loco https://developers.google.com/web/tools/lighthouse/audits/passive-event-listeners
Wheel-Listener sollten immer noch passiv sein, auch wenn Scroll-Listener nicht sein müssen. Ich denke, das kann die Quelle der Verwirrung sein.

@sebmarkbage Was denkst du? Wird diese passive Event-Listener-Unterstützung irgendwann in React Einzug halten?

Hi,

Ich musste nur einen aktiven Ereignis-Listener in componentDidMount wie folgt hinzufügen:

global.addEventListener("touchstart", this.touchStart(), { passive: false })

damit ich e.preventDefault() aufrufen kann, um das Standard-Scrollen von Chrome zu stoppen und ein Element in touchStart() .

Um zu wissen, welches Element ich verschieben muss, musste ich onTouchStart wie folgt zum JSX-Element hinzufügen:

onTouchStart={this.touchStartSetElement(element)}

In touchStartSetElement() setze ich eine Zustandseigenschaft element , die ich in touchStart() lesen kann

Wenn React aktive Ereignis-Listener unterstützen würde, würde sich dies auf eine Zeile reduzieren.

Vielen Dank,

Philipp

PS: Wenn Sie versuchen, e.preventDefault() in einem passiven Ereignis-Listener aufzurufen, erhalten Sie in Chrome 56 diesen Fehler:

[Intervention] Kann Default im passiven Ereignis-Listener nicht verhindern, da das Ziel als passiv behandelt wird. Siehe https://www.chromestatus.com/features/5093566007214080

Passive Ereignisse sind bei Chrome 56 durch einen " Eingriff " von Google und das Brechen des Webs irgendwie zum Standard geworden - aber auch das Scrollen wird schneller.

Dies wird immer problematischer, da Safari ab iOS 11.3 auch standardmäßig passiv ist und der klassische Workaround von touch-action:none dort nicht unterstützt wird .

Ich habe einen RFC https://github.com/reactjs/rfcs/pull/28 vorgeschlagen, der es ermöglicht, benutzerdefinierte Ref-Handler zu erstellen, die wie Requisiten funktionieren (dh Sie verwenden Eigenschaften wie onClick aber stattdessen berechnete -Eigenschaftssyntax und der Handler ruft Informationen zu Ref- und Prop-Werten ab und aktualisiert sie). Diese können verwendet werden, um Bibliotheken für fast jeden fortgeschrittenen Anwendungsfall zu erstellen, den Sie haben.

  • Passive, explizit nicht-passive, einmalige und das Erfassen von Ereignissen sind damit einfach zu bewerkstelligen.
  • Mit ihnen können sogar noch weitergehende Dinge als nur die Registrierung von Eventhandlern durchgeführt werden.
  • Aus der Sicht des Benutzers sind sie einfach zu verwenden, übergeben Sie einfach das, was die Bibliothek Ihnen als berechnete Eigenschaft an ein beliebiges Element gibt. zB import {onScroll} from 'react-passive-events'; <div [onScroll]={scrollHandler} />

Ich denke nicht, dass dies der Weg sein sollte, um alle Ereignisse zu registrieren.

Anstatt jedoch komplexe Möglichkeiten für die Registrierung aller möglichen Arten von Ereignissen (Erfassen, Passiv usw.) zu entwickeln, empfehle ich, das Standardverhalten für die meisten Ereignisse (passiv oder nicht passiv) festzulegen und diese registrierten zu verwenden Requisiten für komplexere Anwendungsfälle.

Alle Berührungsereignisse sind jetzt in iOS 11.3 standardmäßig passiv. Daher ist das Aufrufen von event.preventDefault() in jedem Touch-Event-Handler jetzt wirkungslos

https://codesandbox.io/s/l4kpy569ol

Ohne nicht-passive Event-Handler erzwingen zu können, fällt es uns schwer, die iOS 11.3-Änderungen zu umgehen https://github.com/atlassian/react-beautiful-dnd/issues/413

Ich bin gekommen, um zu sehen, wie Vue.js damit umgeht, und ich mag ihren Ansatz sehr :

<!-- the click event's propagation will be stopped -->
<a v-on:click.stop="doThis"></a>

<!-- the submit event will no longer reload the page -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- modifiers can be chained -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- just the modifier -->
<form v-on:submit.prevent></form>

Es gibt diese Liste von Modifikatoren:

  • .halt
  • .verhindern
  • .ergreifen
  • .selbst
  • .wenn
  • .passiv

Und Sie können Events nach Belieben zusammenstellen. Vielleicht kann dies als Inspiration für dieses Thema hilfreich sein.

@KeitIG Ich arbeite an einer Gabel von Vue-Loader, die für React entwickelt wurde

https://github.com/stalniy/react-webpack-loader

Das macht mich traurig

selection_028

Ich bin mir jedoch nicht sicher, ob dies bereits vorgeschlagen wurde - oder ob es für andere als mich sinnvoll ist:

onTouchStart={listener} 

zu

onTouchStart={listener, options}

würde die Übergabe von Optionen wie { passive, true, once: true } einem natürlichen Weg machen, und es würde auch dem addEventListener- Schema entsprechen.

Sich dem Vorschlag von @phaistonian zuzuwenden , würde die Notwendigkeit für jeden der heute existierenden onEventNameCapture Handler beseitigen

@alexreardon Ich denke wirklich, dass dies keine Option ist, da listener, options in einfachem js ein Ausdruck ist, der zu options ausgewertet wird, also ist die obige Konstruktion nicht das, was Sie meinen. Dies würde eine Änderung der Art und Weise erfordern, wie jsx in js kompiliert wird, und wäre eine bahnbrechende Änderung. Ich bezweifle, dass das Reaktionsteam diesen Weg gehen würde.

Meinungen?

Da es sich um einen Ausdruck handelt, könnte es mit derselben Absicht anders gemacht werden.

Es gibt wahrscheinlich viele Möglichkeiten. Zu den Optionen gehören:

import {handler} from 'React';

onTouchStart={handler(listener, options)}
onTouchStart={{listener, options}}

oder

onTouchStart={[listener, options]}

oder

onTouchStart={listener} onTouchStartOptions={options}

Am besten gefällt mir jedoch die Idee, ein Objekt zu übergeben. Das bedarf in jedem Fall einer Lösung.

gibt es jetzt schon eine lösung?

gibt es jetzt schon eine lösung?

Ihre klassischen addEventListener und removeEventListener in componentDidMount bzw. componentWillUnmount .

Ja, das ist scheiße.

Und was denkst du darüber, es mit einem Haken zu lösen?

...
const onClickPassive = useEventListener((e) => {
 console.log('passive event')
}, { passive: true })

return (
  <button onClick={onClickPassive}>Click me</button>
)

@ara4n mit Hook ist gut, aber es braucht immer noch eine klassische Lösung für Nicht-Hook-Reaktion

@sebmarkbage irgendwelche Updates dazu? Chrome hat dies gerade geliefert und unsere App kaputt gemacht.

https://www.chromestatus.com/features/6662647093133312

[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See https://www.chromestatus.com/features/6662647093133312
Es passiert wieder, als ich versucht habe, das Standard-Scrollverhalten im onWheel Ereignis-Listener zu blockieren

@kychanbi Das gleiche wie bei mir, aber ich treffe diesen Fehler nur auf Windows Chrome.

@kychanbi Oh, es ist eine Funktion von Chrome 73, die Wheel/Mousewheel-Ereignis-Listener auf Dokumentebene als passiv behandelt

Sie können die CSS-Eigenschaft für Ihren Komponentencontainer div touch-action verwenden: keine

.Behälter {
Touch-Aktion: keine;
}

@madcher scheint bei Mausereignissen nicht zu funktionieren.
Ich habe es endlich mit nativem Javascript gelöst
element.addEventListener("wheel", eventHandler);

Ein kleiner Ausschnitt, um denen zu helfen, die mit diesem Problem konfrontiert sind:

import React, { useRef, useEffect } from 'react'

const BlockPageScroll = ({ children }) => {
  const scrollRef = useRef(null)
  useEffect(() => {
    const scrollEl = scrollRef.current
    scrollEl.addEventListener('wheel', stopScroll)
    return () => scrollEl.removeEventListener('wheel', stopScroll)
  }, [])
  const stopScroll = e => e.preventDefault()
  return (
    <div ref={scrollRef}>
      {children}
    </div>
  )
}

const Main = () => (
  <BlockPageScroll>
    <div>Scrolling here will only be targeted to inner elements</div>
  </BlockPageScroll>
)

@madcher

Irgendwie funktioniert onWheel Requisiten nicht mit CSS touch-action: none;

    componentRef = React.createRef(null);
    handleWheel = (e) => {
      e.preventDefault();
    }
    render() {
      <Container style={{ touchAction: 'none' }} onWheel={this.handleWheel}>
        ...
      </Container>
    }

bekomme immer noch diesen Fehler:
[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See <URL>

Arbeitsversion

Als Alternative zur Hooks-Lösung von @markpradhan können Sie dies tun, wenn Sie immer noch eine Komponente im alten Stil verwenden:

    componentRef = React.createRef();
    handleWheel = (e) => {
      e.preventDefault();
    }
    componentDidMount() {
      if (this.componentRef.current) {
        this.componentRef.current.addEventListener('wheel', this.handleWheel);
      }
    }
    componentWillUnmount() {
      if (this.componentRef.current) {
        this.componentRef.current.removeEventListener('wheel', this.handleWheel);
      }
    }
    render() {
      <Container ref={this.componentRef}>...</Container>
    }

@Fonger Wahrscheinlich wegen # 14856

So etwas wurde vorgeschlagen, aber hier sind ein paar weitere Ideen.

function MyComponent() {
  function onScroll(event) { /* ... */ }
  onScroll.options = {capture, passive, ...};
  return <div onScroll={onScroll} />;
}

Mit diesem können Sie sich problemlos für passive Ereignisse entscheiden oder Ereignisse erfassen, ohne dass eine Änderung erforderlich ist. Ich war jedoch fasziniert von der Idee eines standardmäßig passiven Ereignis-Listeners. Ich erinnere mich, dass PreventDefault (unter anderem) ein großes Hindernis war, das die Ausführung von React in einem Worker verhindert.

js function MyComponent() { function onScroll(event) { /* ... */ } onScroll.shouldPreventDefault = (event): boolean => { // some logic to decide if preventDefault() should be called. } onScroll.shouldStopPropagation = (event): boolean => { // some logic to decide if stopPropagation() should be called. } return <div onScroll={onScroll} />; }
Es wäre schwer sicherzustellen, dass dies nicht zu einer bahnbrechenden Änderung wird, aber wenn dies erzwungen würde, würde der gesamte Code, um zu entscheiden, ob ein Ereignis preventDefault bearbeitet werden muss, im Code isoliert und React wäre in der Lage, dies zu tun Führen Sie nur diesen Teil im Hauptthread aus und führen Sie alles andere in einem separaten Worker oder asynchron aus.

Bis dies behoben ist, wäre es meiner Meinung nach am besten, wenn Verweise auf event.preventDefault() aus den Dokumenten entfernt oder zumindest mit einer Warnung bezüglich der Unfähigkeit von Chrome gekennzeichnet werden, preventDefault bei passiven Ereignissen zu verwenden.

Ich frage mich, welche Auswirkungen die Änderung der Event-Delegation von React v17 hat. Lighthouse hat eine Regel https://web.dev/uses-passive-event-listeners/ , die auf nicht-passive Ereignisse testet.

Zuvor wurde <div onTouchStart /> im Dokument registriert, das standardmäßig passiv ist . Mit React v17 wird das Ereignis jedoch an der Wurzel des React-Baums registriert, der nicht mehr passiv ist, ohne ausdrücklich danach zu fragen.

Wiedergabe: https://codesandbox.io/s/material-demo-forked-e2u72?file=/demo.js , live: https://csb-e2u72.netlify.app/

Capture d’écran 2020-08-19 à 16 11 31

Ja. Scheint besorgniserregend zu sein. Ich werde eine neue Ausgabe einreichen.

Eingereicht https://github.com/facebook/react/issues/19651 für die React 17-Diskussion.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen