React: Mendukung Pendengar Acara Pasif

Dibuat pada 7 Apr 2016  ·  62Komentar  ·  Sumber: facebook/react

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

Akan lebih baik jika semuanya pasif secara default dan hanya memilih untuk aktif saat diperlukan. Misalnya, Anda dapat mendengarkan peristiwa input teks tetapi hanya preventDefault atau menggunakan perilaku terkontrol saat Anda memiliki pendengar aktif.

Demikian pula, kita dapat menyatukan ini dengan model threading React Native. Misalnya, satu hal yang dapat kita lakukan di sana adalah memblokir utas UI secara serempak ketika ada pendengar aktif seperti menangani penekanan tombol.

cc @vjeux @ide

DOM React Core Team Big Picture Feature Request

Komentar yang paling membantu

Saya baru saja menekan peringatan di chrome tentang menangani acara roda, yang dapat dioptimalkan jika terdaftar sebagai pengendali acara pasif. Jadi memiliki ini di Bereaksi akan rapi!

Semua 62 komentar

Ini mendarat di Chrome 51. Apakah ada rencana terbaru untuk mendukung ini di Bereaksi? :HAI

Bagaimana ini mungkin jika React hanya memiliki satu event listener di dokumen, dan kemudian mendelegasikannya ke orang lain?
@sebmarkbage

Apa status masalah saat ini dengan Acara Pasif?

Saya baru saja menekan peringatan di chrome tentang menangani acara roda, yang dapat dioptimalkan jika terdaftar sebagai pengendali acara pasif. Jadi memiliki ini di Bereaksi akan rapi!

Anda juga ingin menangani opsi arbitrer, seperti once yang telah mendarat di Firefox setiap malam: https://twitter.com/mozhacks/status/758763803991474176. Daftar lengkap: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener

FWIW, Facebook mendengarkan acara roda aktif untuk memblokir pengguliran luar saat bilah sisi atau jendela obrolan digulir. Kami tidak dapat mengimplementasikan UI tanpanya. Kami masih ingin mendukung ini sebagai opsi tetapi ruang masalahnya masih belum lengkap sehingga mungkin ada solusi alternatif yang berkembang untuk masalah ini yang tidak melibatkan pendengar acara pasif. Jadi itu masih merupakan ruang desain yang aktif.

Sangat penting untuk menjaga kedua pendengar aktif dan menambahkan dukungan yang pasif.
Pada aplikasi desktop Anda tidak melihat perbedaan apa pun, tetapi pada aplikasi seluler, pendengar gulir pasif memberikan peningkatan kecepatan yang luar biasa.

Saran kecil:

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

@romulof ya, ini adalah cara Anda mendaftarkan acara pada fase penangkapan juga

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

jadi saya membayangkan ini akan menjadi API yang tepat untuk mendukung acara pasif juga.

Catatan tambahan: pertanyaan rumit adalah - bagaimana Anda mendaftarkan peristiwa pasif untuk fase penangkapan? Saya kira ini tidak mungkin, karena sifat dari peristiwa pasif. Karena mereka bahkan tidak diizinkan untuk menelepon event.preventDefault() , jadi mungkin ini bukan masalah.

@radubrehar , onScrollCapturePassive terlihat seperti seluruh Alkitab dalam kasus unta.

:) Ini tidak terjadi, karena tidak ada peristiwa pasif pada fase penangkapan.

Tentu itu tidak masuk akal, tapi saya tidak akan mengandalkannya. Ada juga pengikatan acara jenis lain, seperti once .

Saran lain:

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

Dengan cara ini React harus mendeteksi apakah event handler adalah sebuah fungsi (normal binding), atau dan objek yang berisi opsi binding dan fungsi handler.

Saya pikir pendekatan objek dengan opsi lebih masuk akal daripada onFooPassive , karena ada opsi lain yang mungkin diperlukan. Jika dikombinasikan dengan saran @sebmarkbage bahwa acara harus pasif secara default, ini mungkin tidak akan terlalu rumit.

Pendekatan lain yang terlintas dalam pikiran adalah melampirkan properti ke event handler untuk memungkinkan mereka memilih keluar dari mode pasif (atau beralih opsi lain). Sesuatu seperti ini:

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

  handleScroll() {
    ...
  }

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

Secara teori, ini akan bekerja cukup baik dengan dekorator, begitu mereka mendarat.

Memikirkan hal ini sedikit lagi, saya pikir akan lebih baik untuk menambahkan properti opsi acara ke fungsi, daripada opsi individual. Itu akan memungkinkan React untuk hanya perlu mengkhawatirkan satu properti daripada berpotensi banyak. Jadi, untuk menyesuaikan contoh saya di atas:

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

  handleScroll() {
    ...
  }

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

Pikiran lain yang muncul di benak saya adalah seperti apa tampilannya jika kita memodifikasi sintaks JSX dengan cara yang memungkinkan opsi ini diteruskan melalui JSX. Berikut adalah contoh acak yang belum saya pikirkan:

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

Saya juga telah memikirkan apakah acara harus pasif secara default atau tidak, dan saya sedikit ragu. Di satu sisi, ini tentu akan bagus untuk acara seperti scroll handler, tapi saya khawatir itu akan menyebabkan terlalu banyak turbulensi dan perilaku tak terduga bagi banyak handler klik. Kita bisa membuatnya jadi beberapa acara pasif secara default dan yang lain tidak, tapi itu mungkin hanya akan membingungkan orang, jadi mungkin bukan ide yang bagus.

Cara ini sangat mirip dengan apa yang saya usulkan sebelumnya, tanpa memodifikasi sintaks JSX.

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

Dan dokumentasi akan mudah:

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,
    }),
};

Apakah peristiwa reaksi pasif secara default? Tampaknya seperti itu untuk acara sentuh, setidaknya. Saya tidak dapat preventDefault kecuali saya kembali ke pendengar acara tingkat dokumen Vanilla.

@joshjg React handler dilewatkan "event sintetis," yang mirip dengan event asli, tetapi berbeda. Omong-omong, seseorang dengan lebih banyak pengetahuan harus mengoreksi apa yang akan saya katakan karena saya belum benar-benar membaca kode yang melakukan ini.

Saya tidak terlalu paham dengan detail implementasi, tetapi saya tahu bahwa preventDefault bekerja setidaknya _asalkan penangan yang Anda cegah juga merupakan penangan kejadian Bereaksi_. Itu pengalaman saya, sih.

Dengan stopPropagation Anda lebih mungkin kurang beruntung (mis. Anda memiliki pendengar klik document yang tidak dapat terikat dengan React, dan Anda ingin menghindari gelembung jika Anda mengklik di dalam elemen tertentu). Dalam hal ini Anda dapat menggunakan:

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

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

Ini sedikit keluar dari topik utama, tetapi jawaban singkatnya adalah bahwa React tidak menggunakan peristiwa pasif, mereka hanya kadang-kadang ditangani dalam urutan yang aneh.

@joshjg @benwiley4000 @gaearon Baru-baru ini tim chrome telah mengubah pendekatan mereka ke peristiwa sentuh tingkat dokumen, menjadikannya pasif secara default. Dan karena React melampirkan acara di tingkat dokumen, Anda mendapatkan perilaku baru ini.

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

Ini secara tidak langsung telah mengubah cara React berperilaku - saya kira React tidak secara eksplisit menyebutkan passive: false saat melampirkan acara - karenanya perubahan perilaku.

Saya baru saja menekan ini juga - jadi Anda perlu mendaftarkan acara sentuh dengan tangan, dengan addEventListener

Perhatikan bahwa intervensi pasif secara default Chrome hanya berlaku untuk touchstart dan touchmove , bukan wheel . Jadi acara wheel tanpa {passive: true} eksplisit masih akan memaksa pengguliran sinkron, untuk pengguliran roda mouse dan trackpad dua jari. (Saya menulis posting blog tentang beberapa seluk-beluk di sini.)

Kami juga (tim Edge) tidak memiliki niat untuk menerapkan intervensi yang sama, jadi ketika kami mengirimkan event listener pasif, Anda masih ingin secara eksplisit menentukan {passive: true} .

FYI, saya mulai menuruni jalur pasif: palsu untuk mencegah badan menggulir di ponsel ketika ada div pengguliran, tetapi agak berat untuk menggunakan preventDefault() untuk memblokir pengguliran. Saya bisa menambah dan menghapus handler tergantung apakah div ada, atau kembali ke pendekatan body.height = 100%. Perbaikan body.height terasa sedikit kacau, tapi kemudian saya tidak perlu pasif: false sama sekali.

Kasus penggunaan saya adalah bahwa saya ingin menggunakan metode event.preventDefault() untuk mencegah pengguliran wadah ketika pengguna menyeret elemen di dalamnya.

Untuk itu, saya perlu mendaftarkan pendengar acara sebagai non-pasif (pasif: salah).
Karena browser beralih ke pasif: true secara default, saya ingin dapat melakukan yang sebaliknya

Sayangnya saya tidak dapat menggunakan gaya touch-action: none; karena itu diterapkan setelah sentuhan dimulai dan mungkin itu sebabnya itu tidak berpengaruh.

Ini memang akan menjadi masalah segera, saya terkejut bahwa dalam dua tahun tidak ada solusi yang ditemukan. Dan membuat event listener secara manual adalah anti-pola di React.

Dan jika itu menciptakan perubahan yang merusak, maka biarlah. Saya mungkin kehilangan bagian dari cerita meskipun.

Saya suka tanda tangan pendengar acara baru yang diusulkan oleh @romulof di https://github.com/facebook/react/issues/6436#issuecomment -254331351.
Selain memperbaiki masalah yang dijelaskan di sini, dimungkinkan untuk menentukan EventListenerOptions lain seperti once

Saya baru saja mengalami masalah ini. Saya memiliki kanvas tempat pengguna dapat menggambar. Saat menggambar di Android terkadang akan 'menarik untuk menyegarkan' alih-alih melakukan goresan cat. Ini menunjukkan bahwa ini adalah masalah dunia nyata. Saya akan menghindari onTouch{Start,Move,End} untuk saat ini dan secara manual menggunakan addEventListener sebagai solusi.

Saya sangat menyukai pendekatan yang disarankan @romulof . Tampaknya solusi itu juga tidak memerlukan perubahan yang melanggar.

@bobvanderlinden Menambahkan touch-action: none; ke gaya kanvas Anda akan berhasil untuk Anda, itu benar-benar bersinar untuk kasus penggunaan itu. Nilai -nilai lain yang mungkin juga bisa sangat nyaman.

Namun seperti yang ditunjukkan @piotr-cz, touch-action tidak secara universal menyelesaikan masalah peristiwa pasif ini secara keseluruhan. Saya juga mengalami masalah yang sama untuk mencegah wadah dari menggulir saat menyeret elemen anak. Semua solusi cukup rumit dan menambah utang teknis.

Sayangnya kehadiran pendengar non-pasif dapat menyebabkan jank yang signifikan, bahkan jika tidak ada penangan userland yang benar-benar terhubung dengannya. Chrome akan memberi tahu Anda tentang hal itu di level log verbose : [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. (ini adalah penangan tingkat atas yang ditambahkan oleh https://github.com/facebook/react/blob/92b7b172cce9958b846844f0b46fd7bbd8c5140d/packages/ react-dom/src/events/ReactDOMEventListener.js#L155)

@romulof @lencioni @radubrehar Apakah Anda mengetahui fakta bahwa flag pasif tidak dimaksudkan untuk digunakan pada pendengar acara gulir? Ini harus digunakan pada acara seperti touchmove dll. agar tidak mengganggu kinerja pengguliran browser. Contoh Anda sangat membingungkan bagi saya.

Menyetel pasif tidak penting untuk acara gulir dasar, karena tidak dapat dibatalkan, sehingga pendengarnya tetap tidak dapat memblokir rendering halaman.

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

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

Ya, saya sadar akan hal ini sekarang. Saya salah informasi ketika saya menulis saya sebelumnya
komentar. Terima kasih telah mengklarifikasi!

Pada Rabu, 6 Desember 2017, 08:25 Martin Hofmann [email protected]
menulis:

@romulof https://github.com/romulof @lencioni
https://github.com/lencioni @radubrehar https://github.com/radubrehar
Apakah Anda menyadari fakta bahwa bendera pasif tidak dimaksudkan untuk digunakan pada
gulir pendengar acara? Itu harus digunakan pada acara-acara seperti touchmove dll.
agar tidak mengganggu kinerja pengguliran browser. Contoh Anda
sangat membingungkan bagi saya.

Mengatur pasif tidak penting untuk acara gulir dasar, karena tidak bisa
dibatalkan, sehingga pendengarnya tidak dapat memblokir rendering halaman.

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

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


Anda menerima ini karena Anda disebutkan.

Balas email ini secara langsung, lihat di GitHub
https://github.com/facebook/react/issues/6436#issuecomment-349691618 ,
atau matikan utasnya
https://github.com/notifications/unsubscribe-auth/AAL7zgbNCpHNui-TX7r2FYdhVxZfdBX8ks5s9r_4gaJpZM4ICWsW
.

@el-moalo-loco, saya cukup yakin bahwa saya membaca beberapa dokumentasi di situs Google Developers tentang menggunakan pendengar pasif untuk acara gulir untuk meningkatkan kinerja. Saya pasti salah membaca atau ada yang berubah di sepanjang jalan. Bagaimanapun, terima kasih banyak atas klarifikasinya!

@romulof @lencioni @el-moalo-loco https://developers.google.com/web/tools/lighthouse/audits/passive-event-listeners
Pendengar roda harus tetap pasif meskipun pendengar gulir tidak harus demikian. Saya pikir itu mungkin sumber kebingungan.

@sebmarkbage Bagaimana menurut Anda? Akankah dukungan pendengar acara pasif ini masuk ke React kapan-kapan?

Hai,

Saya baru saja menambahkan pendengar acara aktif di componentDidMount seperti ini:

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

sehingga saya dapat memanggil e.preventDefault() untuk menghentikan pengguliran default Chrome dan memindahkan elemen di touchStart() .

Untuk mengetahui elemen mana yang harus saya pindahkan, saya harus menambahkan onTouchStart ke elemen BEJ seperti ini:

onTouchStart={this.touchStartSetElement(element)}

Di touchStartSetElement() Saya menetapkan properti negara element yang dapat saya baca di touchStart()

Jika Bereaksi akan mendukung pendengar acara aktif, ini akan menjadi satu baris.

Terima kasih,

Philipp

PS: Jika Anda mencoba memanggil e.preventDefault() di pendengar acara pasif, Anda mendapatkan kesalahan ini di Chrome 56:

[Intervensi] Tidak dapat mencegah Default di dalam pendengar acara pasif karena target diperlakukan sebagai pasif. Lihat https://www.chromestatus.com/features/5093566007214080

Acara pasif telah menjadi default dengan Chrome 56 oleh " intervensi " Google dan entah bagaimana merusak web - tetapi juga membuat pengguliran lebih cepat.

Ini menjadi lebih menjadi masalah karena Safari pada iOS 11.3 juga default ke pasif, dan solusi klasik touch-action:none tidak didukung di sana .

Saya telah mengusulkan RFC https://github.com/reactjs/rfcs/pull/28 yang memungkinkan pembuatan penangan ref khusus yang berfungsi seperti alat peraga (yaitu Anda menggunakan properti seperti onClick tetapi sebaliknya menggunakan yang dihitung sintaks properti dan pawang mendapat info dan pembaruan nilai ref dan prop). Ini dapat digunakan untuk membuat perpustakaan untuk hampir semua kasus penggunaan lanjutan yang Anda miliki.

  • Pasif, eksplisit non-pasif, sekali, dan menangkap peristiwa semuanya mudah dilakukan dengannya.
  • Hal-hal yang bahkan lebih maju dari sekedar pendaftaran event handler dapat dilakukan dengan mereka.
  • Dari sudut pandang pengguna, mereka mudah digunakan, cukup berikan apa yang diberikan perpustakaan kepada Anda sebagai properti yang dihitung ke elemen apa pun. misalnya import {onScroll} from 'react-passive-events'; <div [onScroll]={scrollHandler} />

Saya tidak berpikir ini harus menjadi cara untuk mendaftarkan semua peristiwa.

Namun, alih-alih menemukan cara rumit untuk menangani pendaftaran semua jenis peristiwa yang mungkin (menangkap, pasif, dll ...) Saya sarankan memutuskan apa perilaku default seharusnya untuk sebagian besar peristiwa (pasif atau non-pasif) dan menggunakan ini terdaftar props untuk menangani kasus penggunaan yang lebih canggih.

Semua acara sentuh sekarang pasif secara default di iOS 11.3. Jadi memanggil event.preventDefault() di event handler sentuh apa pun sekarang tidak efektif

https://codesandbox.io/s/l4kpy569ol

Tanpa dapat memaksa event handler non-pasif, kami mengalami kesulitan mengatasi perubahan iOS 11.3 https://github.com/atlassian/react-beautiful-dnd/issues/413

Saya datang untuk melihat bagaimana Vue.js menangani ini, dan saya sangat menyukai pendekatan mereka :

<!-- 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>

Ada daftar pengubah ini:

  • .berhenti
  • .mencegah
  • .menangkap
  • .diri sendiri
  • .satu kali
  • .pasif

Dan Anda dapat membuat acara sesuai keinginan Anda. Mungkin ini bisa membantu sebagai inspirasi untuk masalah ini.

@KeitIG Saya sedang mengerjakan garpu Vue-loader yang dirancang untuk Bereaksi

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

Ini membuatku sedih

selection_028

Tidak yakin apakah ini sudah disarankan - atau apakah itu masuk akal bagi orang lain selain saya, namun:

onTouchStart={listener} 

ke

onTouchStart={listener, options}

keduanya akan membuat opsi lewat seperti { passive, true, once: true } cara alami untuk melakukannya, dan itu juga akan cocok dengan skema addEventListener .

Bergerak menuju saran @phaistonian akan menghilangkan kebutuhan akan penangan onEventNameCapture yang ada saat ini

@alexreardon Saya benar-benar berpikir itu bukan pilihan, karena dalam js biasa, listener, options adalah ekspresi, yang dievaluasi menjadi options , jadi konstruksi di atas bukan seperti yang Anda maksudkan. Ini akan membutuhkan mengubah cara jsx mengkompilasi ke js dan akan menjadi perubahan yang melanggar. Saya ragu tim reaksi akan menempuh rute ini.

Pendapat?

Mengenai itu sebagai ekspresi, itu bisa dilakukan secara berbeda dengan niat yang sama.

Mungkin ada banyak pilihan. Pilihan meliputi:

import {handler} from 'React';

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

atau

onTouchStart={[listener, options]}

atau

onTouchStart={listener} onTouchStartOptions={options}

Saya paling suka ide melewati objek. Bagaimanapun, ini membutuhkan solusi.

apakah sekarang sudah ada solusinya?

apakah sekarang sudah ada solusinya?

addEventListener dan removeEventListener klasik Anda masing-masing di componentDidMount dan componentWillUnmount .

Ya, itu menyebalkan.

Dan apa pendapat Anda tentang menyelesaikannya menggunakan kail?

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

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

@ara4n menggunakan hook itu bagus, tetapi masih membutuhkan solusi klasik untuk reaksi non-hook

@sebmarkbage ada pembaruan tentang ini? Chrome baru saja mengirimkan ini dan merusak aplikasi kami.

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

[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See https://www.chromestatus.com/features/6662647093133312
Itu terjadi lagi, ketika saya mencoba untuk memblokir perilaku pengguliran default di pendengar acara onWheel

@kychanbi Sama dengan saya, tetapi saya hanya menemukan kesalahan ini di Windows chrome.

@kychanbi Oh, ini adalah fitur Chrome 73 yang memperlakukan pendengar acara Roda/Roda Mouse tingkat dokumen sebagai Pasif

Anda dapat menggunakan properti css pada tindakan sentuh div wadah komponen Anda: tidak ada

.wadah {
sentuhan-aksi: tidak ada;
}

@madcher sepertinya tidak berfungsi untuk acara mouse.
Saya akhirnya menyelesaikannya dengan menggunakan javascript asli
element.addEventListener("wheel", eventHandler);

Cuplikan kecil untuk membantu mereka yang menghadapi masalah ini:

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

Entah bagaimana onWheel props tidak berfungsi dengan css touch-action: none;

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

masih mendapatkan kesalahan ini:
[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See <URL>

Versi Kerja

alternatif dari solusi kait @markpradhan , jika Anda masih menggunakan komponen gaya lama, Anda dapat melakukan ini:

    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 Mungkin karena #14856

Sesuatu seperti ini telah disarankan tetapi di sini ada beberapa ide lagi.

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

Yang ini akan memungkinkan Anda dengan mudah memilih acara pasif atau menangkap acara tanpa perlu perubahan besar. Namun, saya tertarik dengan ide pendengar acara pasif secara default. Saya ingat preventDefault menjadi kendala utama (antara lain) yang menghalangi React berjalan di pekerja.

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} />; }
Akan sulit untuk memastikan ini tidak menjadi perubahan yang merusak, tetapi jika ini diterapkan, semua kode untuk memutuskan apakah suatu acara perlu preventDefault ed akan diisolasi dalam kode dan React akan dapat jalankan hanya bagian itu di utas utama dan jalankan yang lainnya di pekerja terpisah atau secara asinkron.

Sampai ini diselesaikan, saya pikir akan lebih baik jika referensi ke event.preventDefault() dihapus dari dokumen atau setidaknya ditandai dengan peringatan tentang ketidakmampuan Chrome untuk preventDefault pada acara pasif.

Saya bertanya-tanya tentang implikasi dari perubahan delegasi acara dari React v17. Lighthouse memiliki aturan https://web.dev/uses-passive-event-listeners/ yang menguji peristiwa non-pasif.

Sebelumnya, <div onTouchStart /> akan didaftarkan pada dokumen, yang secara default pasif . Namun, dengan React v17, acara tersebut terdaftar di akar pohon React, yang tidak lagi pasif tanpa secara khusus memintanya.

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

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

Ya. Tampaknya memprihatinkan. Saya akan mengajukan masalah baru.

Diarsipkan https://github.com/facebook/react/issues/19651 untuk diskusi React 17.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat