React: μˆ˜λ™ 이벀트 λ¦¬μŠ€λ„ˆ 지원

에 λ§Œλ“  2016λ…„ 04μ›” 07일  Β·  62μ½”λ©˜νŠΈ  Β·  좜처: facebook/react

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

λͺ¨λ“  것을 기본적으둜 μˆ˜λ™μ μœΌλ‘œ μ„€μ •ν•˜κ³  ν•„μš”ν•  λ•Œλ§Œ ν™œμ„±ν™”ν•˜λ„λ‘ μ„ νƒν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ ν…μŠ€νŠΈ μž…λ ₯ 이벀트λ₯Ό μˆ˜μ‹ ν•  수 μžˆμ§€λ§Œ ν™œμ„± λ¦¬μŠ€λ„ˆκ°€ μžˆλŠ” κ²½μš°μ—λŠ” preventDefault λ˜λŠ” μ œμ–΄λœ λ™μž‘λ§Œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ§ˆμ°¬κ°€μ§€λ‘œ 이것을 React Native의 μŠ€λ ˆλ”© λͺ¨λΈκ³Ό 톡합할 수 μžˆμŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ μš°λ¦¬κ°€ ν•  수 μžˆλŠ” ν•œ κ°€μ§€λŠ” ν‚€ μž…λ ₯ μ²˜λ¦¬μ™€ 같은 ν™œμ„± λ¦¬μŠ€λ„ˆκ°€ μžˆμ„ λ•Œ UI μŠ€λ ˆλ“œλ₯Ό λ™κΈ°μ μœΌλ‘œ μ°¨λ‹¨ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

cc @vjeux @ide

DOM React Core Team Big Picture Feature Request

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

μˆ˜λ™ 이벀트 ν•Έλ“€λŸ¬λ‘œ λ“±λ‘λœ 경우 μ΅œμ ν™”λ  수 μžˆλŠ” 휠 이벀트 μ²˜λ¦¬μ— λŒ€ν•΄ ν¬λ‘¬μ—μ„œ κ²½κ³ λ₯Ό λ°›μ•˜μŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ Reactμ—μ„œ 이것을 κ°–λŠ” 것은 깔끔할 κ²ƒμž…λ‹ˆλ‹€!

λͺ¨λ“  62 λŒ“κΈ€

이것은 Chrome 51에 상λ₯™ν–ˆμŠ΅λ‹ˆλ‹€. Reactμ—μ„œ 이λ₯Ό μ§€μ›ν•˜κΈ° μœ„ν•œ μ—…λ°μ΄νŠΈλœ κ³„νšμ΄ μžˆμŠ΅λ‹ˆκΉŒ? :μ˜ν˜•

Reactκ°€ λ¬Έμ„œμ— 이벀트 λ¦¬μŠ€λ„ˆκ°€ ν•˜λ‚˜λ§Œ 있고 λ‹€λ₯Έ μ‚¬λžŒμ—κ²Œ μœ„μž„ν•˜λŠ” 경우 이것이 μ–΄λ–»κ²Œ κ°€λŠ₯ν•©λ‹ˆκΉŒ?
@sebmarkbage

μˆ˜λ™ 이벀트 문제의 ν˜„μž¬ μƒνƒœλŠ” λ¬΄μ—‡μž…λ‹ˆκΉŒ?

μˆ˜λ™ 이벀트 ν•Έλ“€λŸ¬λ‘œ λ“±λ‘λœ 경우 μ΅œμ ν™”λ  수 μžˆλŠ” 휠 이벀트 μ²˜λ¦¬μ— λŒ€ν•΄ ν¬λ‘¬μ—μ„œ κ²½κ³ λ₯Ό λ°›μ•˜μŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ Reactμ—μ„œ 이것을 κ°–λŠ” 것은 깔끔할 κ²ƒμž…λ‹ˆλ‹€!

λ˜ν•œ 야간에 Firefox에 이미 λ„μ°©ν•œ once 와 같은 μž„μ˜μ˜ μ˜΅μ…˜μ„ μ²˜λ¦¬ν•˜κ³  싢을 μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€: https://twitter.com/mozhacks/status/758763803991474176. 전체 λͺ©λ‘: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener

FWIW, Facebook은 μ‚¬μ΄λ“œλ°” λ˜λŠ” μ±„νŒ… 창이 슀크둀될 λ•Œ μ™ΈλΆ€ μŠ€ν¬λ‘€μ„ μ°¨λ‹¨ν•˜κΈ° μœ„ν•΄ ν™œμ„± 휠 이벀트λ₯Ό μˆ˜μ‹ ν•©λ‹ˆλ‹€. UI μ—†μ΄λŠ” UIλ₯Ό κ΅¬ν˜„ν•  수 μ—†μŠ΅λ‹ˆλ‹€. μš°λ¦¬λŠ” μ—¬μ „νžˆ 이것을 μ˜΅μ…˜μœΌλ‘œ μ§€μ›ν•˜κΈ°λ₯Ό μ›ν•˜μ§€λ§Œ 문제 곡간은 μ—¬μ „νžˆ β€‹β€‹λΆˆμ™„μ „ν•˜λ―€λ‘œ μˆ˜λ™ 이벀트 λ¦¬μŠ€λ„ˆλ₯Ό ν¬ν•¨ν•˜μ§€ μ•ŠλŠ” 이 λ¬Έμ œμ— λŒ€ν•œ λŒ€μ•ˆ μ†”λ£¨μ…˜μ΄ λ°œμ „ν•  수 μžˆμŠ΅λ‹ˆλ‹€. κ·Έλž˜μ„œ μ—¬μ „νžˆ ν™œλ°œν•œ λ””μžμΈ κ³΅κ°„μž…λ‹ˆλ‹€.

두 ν™œμ„± 청취자λ₯Ό μœ μ§€ν•˜κ³  지원 μˆ˜λ™ 청취자λ₯Ό μΆ”κ°€ν•˜λŠ” 것이 μ€‘μš”ν•©λ‹ˆλ‹€.
λ°μŠ€ν¬ν†± μ‘μš© ν”„λ‘œκ·Έλž¨μ—μ„œλŠ” 차이가 λ‚˜νƒ€λ‚˜μ§€ μ•Šμ§€λ§Œ λͺ¨λ°”일 μ‘μš© ν”„λ‘œκ·Έλž¨μ—μ„œλŠ” μˆ˜λ™ 슀크둀 μˆ˜μ‹ κΈ°κ°€ 속도λ₯Ό 크게 ν–₯μƒμ‹œν‚΅λ‹ˆλ‹€.

μž‘μ€ μ œμ•ˆ:

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

@romulof 예, 캑처 λ‹¨κ³„μ—μ„œλ„ 이벀트λ₯Ό λ“±λ‘ν•˜λŠ” λ°©λ²•μž…λ‹ˆλ‹€.

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

κ·Έλž˜μ„œ 이것이 νŒ¨μ‹œλΈŒ μ΄λ²€νŠΈλ„ μ§€μ›ν•˜λŠ” μ μ ˆν•œ APIκ°€ 될 것이라고 μƒκ°ν•©λ‹ˆλ‹€.

μ°Έκ³  사항: κΉŒλ‹€λ‘œμš΄ μ§ˆλ¬Έμ€ - 캑처 λ‹¨κ³„μ—μ„œ μˆ˜λ™ 이벀트λ₯Ό μ–΄λ–»κ²Œ λ“±λ‘ν•©λ‹ˆκΉŒ? μ†Œκ·Ήμ μΈ μ‚¬κ±΄μ˜ νŠΉμ„±μƒ λΆˆκ°€λŠ₯ν•œ 일이라고 μƒκ°ν•©λ‹ˆλ‹€. event.preventDefault() λ₯Ό ν˜ΈμΆœν•˜λŠ” 것쑰차 ν—ˆμš©λ˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— 이것은 μ•„λ§ˆλ„ λ¬Έμ œκ°€ λ˜μ§€ μ•Šμ„ κ²ƒμž…λ‹ˆλ‹€.

@radubrehar , onScrollCapturePassive λŠ” 낙타 μΌ€μ΄μŠ€μ˜ 전체 μ„±κ²½μ²˜λŸΌ λ³΄μž…λ‹ˆλ‹€.

:) 캑처 단계에 μˆ˜λ™ μ΄λ²€νŠΈκ°€ μ—†κΈ° λ•Œλ¬Έμ— 그렇지 μ•ŠμŠ΅λ‹ˆλ‹€.

λ¬Όλ‘  μ˜λ―Έκ°€ μ—†μ§€λ§Œ, λ‚˜λŠ” 그것에 μ˜μ‘΄ν•˜μ§€ μ•Šμ„ κ²ƒμž…λ‹ˆλ‹€. once 와 같은 λ‹€λ₯Έ μœ ν˜•μ˜ 이벀트 바인딩도 μžˆμŠ΅λ‹ˆλ‹€.

또 λ‹€λ₯Έ μ œμ•ˆ:

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

이런 μ‹μœΌλ‘œ ReactλŠ” 이벀트 ν•Έλ“€λŸ¬κ°€ ν•¨μˆ˜μΈμ§€(일반 바인딩) 바인딩 μ˜΅μ…˜κ³Ό ν•Έλ“€λŸ¬ ν•¨μˆ˜λ₯Ό ν¬ν•¨ν•˜λŠ” 객체인지 감지해야 ν•©λ‹ˆλ‹€.

ν•„μš”ν•  수 μžˆλŠ” λ‹€λ₯Έ μ˜΅μ…˜μ΄ 있기 λ•Œλ¬Έμ— μ˜΅μ…˜μ΄ μžˆλŠ” 개체 μ ‘κ·Ό 방식이 onFooPassive 보닀 더 합리적이라고 μƒκ°ν•©λ‹ˆλ‹€. μ΄λ²€νŠΈκ°€ 기본적으둜 μˆ˜λ™μ μ΄μ–΄μ•Ό ν•œλ‹€λŠ” @sebmarkbage 의 μ œμ•ˆκ³Ό κ²°ν•©ν•˜λ©΄

μƒκ°λ‚˜λŠ” 또 λ‹€λ₯Έ μ ‘κ·Ό 방식은 이벀트 ν•Έλ“€λŸ¬μ— 속성을 μΆ”κ°€ν•˜μ—¬ νŒ¨μ‹œλΈŒ λͺ¨λ“œμ—μ„œ μ˜΅νŠΈμ•„μ›ƒ(λ˜λŠ” λ‹€λ₯Έ μ˜΅μ…˜μ„ ν† κΈ€)ν•  수 μžˆλ„λ‘ ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. 이 같은:

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

  handleScroll() {
    ...
  }

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

이둠적으둜 이것은 λ°μ½”λ ˆμ΄ν„°κ°€ μ°©λ₯™ν•˜λ©΄ κ½€ 잘 μž‘λ™ν•©λ‹ˆλ‹€.

이에 λŒ€ν•΄ 쑰금 더 생각해보면 κ°œλ³„ μ˜΅μ…˜λ³΄λ‹€λŠ” 이벀트 μ˜΅μ…˜ 속성을 ν•¨μˆ˜μ— μΆ”κ°€ν•˜λŠ” 것이 더 λ‚˜μ„ 것 κ°™λ‹€. 그러면 ReactλŠ” 잠재적으둜 λ§Žμ€ 속성 λŒ€μ‹ μ— ν•˜λ‚˜μ˜ μ†μ„±λ§Œ κ±±μ •ν•˜λ©΄ λ©λ‹ˆλ‹€. λ”°λΌμ„œ μœ„μ˜ 예λ₯Ό μ‘°μ •ν•˜λ €λ©΄ λ‹€μŒμ„ μˆ˜ν–‰ν•˜μ‹­μ‹œμ˜€.

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

  handleScroll() {
    ...
  }

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

또 λ‹€λ₯Έ 생각은 μ΄λŸ¬ν•œ μ˜΅μ…˜μ΄ JSXλ₯Ό 톡해 μ „λ‹¬λ˜λ„λ‘ ν—ˆμš©ν•˜λŠ” λ°©μ‹μœΌλ‘œ JSX ꡬ문 을 μƒκ²Όμ„κΉŒ ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. λ‹€μŒμ€ λ‚΄κ°€ 많이 μƒκ°ν•˜μ§€ μ•Šμ€ μž„μ˜μ˜ μ˜ˆμž…λ‹ˆλ‹€.

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

λ‚˜λŠ” λ˜ν•œ μ΄λ²€νŠΈκ°€ 기본적으둜 μˆ˜λ™μ μ΄μ–΄μ•Ό ν•˜λŠ”μ§€ 여뢀에 λŒ€ν•΄ μƒκ°ν•˜κ³  있으며, λ‚˜λŠ” μ•½κ°„ κ²½κ³„ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. ν•œνŽΈμœΌλ‘œ 이것은 슀크둀 ν•Έλ“€λŸ¬μ™€ 같은 μ΄λ²€νŠΈμ— λΆ„λͺ…νžˆ 쒋을 κ²ƒμ΄μ§€λ§Œ λ§Žμ€ 클릭 ν•Έλ“€λŸ¬μ— λ„ˆλ¬΄ λ§Žμ€ λ‚œκΈ°λ₯˜μ™€ 예기치 μ•Šμ€ λ™μž‘μ„ μΌμœΌν‚¬κΉŒ κ±±μ •λ©λ‹ˆλ‹€. 일뢀 μ΄λ²€νŠΈλŠ” 기본적으둜 μˆ˜λ™μ μ΄κ³  λ‹€λ₯Έ μ΄λ²€νŠΈλŠ” 그렇지 μ•Šλ„λ‘ λ§Œλ“€ 수 μžˆμŠ΅λ‹ˆλ‹€.

이 방법은 JSX ꡬ문을 μˆ˜μ •ν•˜μ§€ μ•Šκ³  이전에 μ œμ•ˆν•œ 것과 맀우 μœ μ‚¬ν•©λ‹ˆλ‹€.

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

그리고 λ¬Έμ„œν™”λŠ” 간단할 κ²ƒμž…λ‹ˆλ‹€:

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

λ°˜μ‘ μ΄λ²€νŠΈλŠ” 기본적으둜 μˆ˜λ™μ μž…λ‹ˆκΉŒ? 적어도 ν„°μΉ˜ μ΄λ²€νŠΈμ—μ„œλŠ” 그런 것 κ°™μŠ΅λ‹ˆλ‹€. 바닐라 λ¬Έμ„œ μˆ˜μ€€ 이벀트 λ¦¬μŠ€λ„ˆλ‘œ λŒμ•„κ°€μ§€ μ•ŠλŠ” ν•œ preventDefault ν•  수 μ—†μŠ΅λ‹ˆλ‹€.

@joshjg React ν•Έλ“€λŸ¬λŠ” λ„€μ΄ν‹°λΈŒ μ΄λ²€νŠΈμ™€ λΉ„μŠ·ν•˜μ§€λ§Œ λ‹€λ₯Έ "ν•©μ„± 이벀트"λ₯Ό 전달

λ‚˜λŠ” κ΅¬ν˜„ μ„ΈλΆ€ 사항에 μ΅μˆ™ν•˜μ§€ μ•Šμ§€λ§Œ λ°©μ§€ν•˜λ €λŠ” ν•Έλ“€λŸ¬κ°€ React 이벀트 ν•Έλ“€λŸ¬μΈ ν•œ μ΅œμ†Œν•œ preventDefault μž‘λ™ν•œλ‹€λŠ” 것을 μ•Œκ³  μžˆμŠ΅λ‹ˆλ‹€. μ–΄μ¨Œλ“  제 κ²½ν—˜μ΄μ—ˆμŠ΅λ‹ˆλ‹€.

stopPropagation ν•˜λ©΄ 운이 쒋지 μ•Šμ„ κ°€λŠ₯성이 더 λ†’μŠ΅λ‹ˆλ‹€(예: React와 κ²°ν•©ν•  수 μ—†λŠ” document 클릭 λ¦¬μŠ€λ„ˆκ°€ 있고 λ‚΄λΆ€λ₯Ό 클릭할 λ•Œ 버블링을 λ°©μ§€ν•˜κ³  μ‹ΆμŠ΅λ‹ˆλ‹€. νŠΉμ • μš”μ†Œ). 이 경우 λ‹€μŒμ„ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

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

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

이것은 μ£Όμš” μ£Όμ œμ—μ„œ μ•½κ°„ λ²—μ–΄λ‚¬μ§€λ§Œ 짧은 λŒ€λ‹΅μ€ Reactκ°€ μˆ˜λ™ 이벀트λ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šκ³  λ•Œλ•Œλ‘œ μ΄μƒν•œ μˆœμ„œλ‘œ μ²˜λ¦¬λœλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€.

@joshjg @benwiley4000 @gaearon μ΅œκ·Όμ— 크둬 νŒ€μ€ λ¬Έμ„œ μˆ˜μ€€ ν„°μΉ˜ μ΄λ²€νŠΈμ— λŒ€ν•œ μ ‘κ·Ό 방식을 λ³€κ²½ν•˜μ—¬ 기본적으둜 μˆ˜λ™μœΌλ‘œ λ§Œλ“€μ—ˆμŠ΅λ‹ˆλ‹€. 그리고 ReactλŠ” λ¬Έμ„œ μˆ˜μ€€μ—μ„œ 이벀트λ₯Ό μ²¨λΆ€ν•˜λ―€λ‘œ 이 μƒˆλ‘œμš΄ λ™μž‘μ„ μ–»κ²Œ λ©λ‹ˆλ‹€.

https://www.chromestatus.com/features/5093566007214080 μ°Έμ‘°

이것은 κ°„μ ‘μ μœΌλ‘œ Reactκ°€ λ™μž‘ν•˜λŠ” 방식을 λ³€κ²½ν–ˆμŠ΅λ‹ˆλ‹€. Reactκ°€ 이벀트λ₯Ό 첨뢀할 λ•Œ passive: false λͺ…μ‹œμ μœΌλ‘œ μ–ΈκΈ‰ν•˜μ§€ μ•ŠλŠ”λ‹€κ³  κ°€μ •ν•©λ‹ˆλ‹€. λ”°λΌμ„œ λ™μž‘μ΄ λ³€κ²½λ©λ‹ˆλ‹€.

λ‚˜λ„ 방금 이것을 μ³€λ‹€ - κ·Έλž˜μ„œ 당신은 addEventListenerλ₯Ό μ‚¬μš©ν•˜μ—¬ μ†μœΌλ‘œ ν„°μΉ˜ 이벀트λ₯Ό 등둝해야 ν•œλ‹€

크둬 μˆ˜λ™ 별 κΈ°λ³Έ κ°œμž…μ—λ§Œ μ μš©λ©λ‹ˆλ‹€ touchstart 및 touchmove ν•˜μ§€ wheel . λ”°λΌμ„œ λͺ…μ‹œμ μΈ {passive: true} κ°€ μ—†λŠ” wheel μ΄λ²€νŠΈλŠ” 마우슀휠 및 두 손가락 νŠΈλž™νŒ¨λ“œ μŠ€ν¬λ‘€μ— λŒ€ν•΄ 동기 μŠ€ν¬λ‘€μ„ 계속 κ°•μ œ μ‹€ν–‰ν•©λ‹ˆλ‹€. (μ—¬κΈ°μ„œ λͺ‡ 가지 λ―Έλ¬˜ν•œ 뢀뢄에 λŒ€ν•΄ λΈ”λ‘œκ·Έ κ²Œμ‹œλ¬Όμ„ μž‘μ„±ν–ˆμŠ΅λ‹ˆλ‹€.)

λ˜ν•œ 우리(Edge νŒ€)λŠ” λ™μΌν•œ κ°œμž…μ„ κ΅¬ν˜„ν•  μ˜λ„κ°€ μ—†μœΌλ―€λ‘œ μˆ˜λ™ 이벀트 λ¦¬μŠ€λ„ˆλ₯Ό μ œκ³΅ν•  λ•Œ {passive: true} λ₯Ό λͺ…μ‹œμ μœΌλ‘œ μ§€μ •ν•˜κΈ°λ₯Ό 원할 κ²ƒμž…λ‹ˆλ‹€.

참고둜, 슀크둀 divκ°€ μžˆμ„ λ•Œ λͺ¨λ°”μΌμ—μ„œ 본문이 μŠ€ν¬λ‘€λ˜λŠ” 것을 λ°©μ§€ν•˜κΈ° μœ„ν•΄ passive: false 경둜둜 μ΄λ™ν•˜κΈ° μ‹œμž‘ν–ˆμ§€λ§Œ, μŠ€ν¬λ‘€μ„ μ°¨λ‹¨ν•˜κΈ° μœ„ν•΄ preventDefault()λ₯Ό μ‚¬μš©ν•˜λŠ” 것은 μ•½κ°„ λ¬΄κ²μŠ΅λ‹ˆλ‹€. divκ°€ μžˆλŠ”μ§€ 여뢀에 따라 ν•Έλ“€λŸ¬λ₯Ό μΆ”κ°€ 및 μ œκ±°ν•˜κ±°λ‚˜ body.height = 100% μ ‘κ·Ό λ°©μ‹μœΌλ‘œ λŒ€μ²΄ν•  수 μžˆμŠ΅λ‹ˆλ‹€. body.height μˆ˜μ •μ€ μ•½κ°„ ν•΄ν‚Ήλœ λŠλ‚Œμ΄ λ“€μ§€λ§Œ μˆ˜λ™: falseκ°€ μ „ν˜€ ν•„μš”ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

λ‚΄ μ‚¬μš© μ‚¬λ‘€λŠ” event.preventDefault() λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ μ‚¬μš©μžκ°€ λ‚΄λΆ€μ—μ„œ μš”μ†Œλ₯Ό 끌 λ•Œ μ»¨ν…Œμ΄λ„ˆ μŠ€ν¬λ‘€μ„ λ°©μ§€ν•˜κ³  μ‹ΆμŠ΅λ‹ˆλ‹€.

이λ₯Ό μœ„ν•΄μ„œλŠ” 이벀트 λ¦¬μŠ€λ„ˆλ₯Ό non-passive(passive: false)둜 등둝해야 ν•©λ‹ˆλ‹€.
λΈŒλΌμš°μ €κ°€ μˆ˜λ™μœΌλ‘œ μ „ν™˜ν•¨μ— 따라 기본적으둜 true, λ‚˜λŠ” λ°˜λŒ€λ‘œ ν•  수 있기λ₯Ό μ›ν•©λ‹ˆλ‹€.

λΆˆν–‰νžˆλ„ touch-action: none; μŠ€νƒ€μΌμ„ μ‚¬μš©ν•  수 μ—†μŠ΅λ‹ˆλ‹€. ν„°μΉ˜κ°€ μ‹œμž‘λœ 후에 적용되고 있고 μ•„λ§ˆλ„ μ•„λ¬΄λŸ° νš¨κ³Όκ°€ μ—†κΈ° λ•Œλ¬ΈμΌ κ²ƒμž…λ‹ˆλ‹€.

그것은 μ •λ§λ‘œ 곧 λ¬Έμ œκ°€ 될 κ²ƒμž…λ‹ˆλ‹€. μ €λŠ” 2λ…„ λ™μ•ˆ 해결책을 찾지 λͺ»ν–ˆλ‹€λŠ” 사싀에 λ†€λžμŠ΅λ‹ˆλ‹€. 그리고 μˆ˜λ™μœΌλ‘œ 이벀트 λ¦¬μŠ€λ„ˆλ₯Ό μƒμ„±ν•˜λŠ” 것은 Reactμ—μ„œ μ•ˆν‹° νŒ¨ν„΄μž…λ‹ˆλ‹€.

그리고 그것이 μ£Όμš” λ³€κ²½ 사항을 μƒμ„±ν•˜λŠ” κ²½μš°μ—λ„ λ§ˆμ°¬κ°€μ§€μž…λ‹ˆλ‹€. κ·Έλž˜λ„ μ΄μ•ΌκΈ°μ˜ 일뢀λ₯Ό 놓칠 수 μžˆμŠ΅λ‹ˆλ‹€.

https://github.com/facebook/react/issues/6436#issuecomment -254331351μ—μ„œ @romulof κ°€ μ œμ•ˆν•œ μƒˆλ‘œμš΄ 이벀트 λ¦¬μŠ€λ„ˆ μ„œλͺ…이
여기에 μ„€λͺ…λœ 문제λ₯Ό μˆ˜μ •ν•˜λŠ” 것 외에도 once 와 같은 λ‹€λ₯Έ EventListenerOptionsλ₯Ό 지정할 수 μžˆμŠ΅λ‹ˆλ‹€.

방금이 λ¬Έμ œκ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. μ‚¬μš©μžκ°€ 그릴 수 μžˆλŠ” μΊ”λ²„μŠ€κ°€ μžˆμŠ΅λ‹ˆλ‹€. Androidμ—μ„œ 그림을 그릴 λ•Œ 페인트 칠을 ν•˜λŠ” λŒ€μ‹  'μƒˆλ‘œ κ³ μΉ¨'을 ν•˜λŠ” κ²½μš°κ°€ μžˆμŠ΅λ‹ˆλ‹€. 이것은 그것이 ν˜„μ‹€ μ„Έκ³„μ˜ λ¬Έμ œμž„μ„ λ³΄μ—¬μ€λ‹ˆλ‹€. μ§€κΈˆμ€ onTouch{Start,Move,End} 을 μ‚¬μš©ν•˜μ§€ μ•Šκ³  μˆ˜λ™μœΌλ‘œ addEventListener λ₯Ό ν•΄κ²° λ°©λ²•μœΌλ‘œ μ‚¬μš©ν•˜κ² μŠ΅λ‹ˆλ‹€.

@romulofκ°€ μ œμ•ˆν•œ μ ‘κ·Ό 방식을 맀우 μ’‹μ•„ν•©λ‹ˆλ‹€. μ†”λ£¨μ…˜μ—λ„ μ£Όμš” λ³€κ²½ 사항이 ν•„μš”ν•˜μ§€ μ•Šμ€ 것 κ°™μŠ΅λ‹ˆλ‹€.

@bobvanderlinden touch-action: none; 을 μΊ”λ²„μŠ€ μŠ€νƒ€μΌμ— μΆ”κ°€ν•˜λ©΄ νš¨κ³Όκ°€ μžˆμ„ κ²ƒμž…λ‹ˆλ‹€. ν•΄λ‹Ή μ‚¬μš© μ‚¬λ‘€μ—μ„œ 정말 빛을 λ°œν•©λ‹ˆλ‹€. λ‹€λ₯Έ κ°€λŠ₯ν•œ κ°’ 도 맀우 νŽΈλ¦¬ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

κ·ΈλŸ¬λ‚˜ @piotr-czκ°€ μ§€μ ν–ˆλ“―μ΄ touch-action λŠ” 이 μˆ˜λ™ 이벀트 문제λ₯Ό μ „μ²΄μ μœΌλ‘œ ν•΄κ²°ν•˜μ§€ λͺ»ν•©λ‹ˆλ‹€. λ˜ν•œ μžμ‹ μš”μ†Œλ₯Ό λ“œλž˜κ·Έν•˜λŠ” λ™μ•ˆ μ»¨ν…Œμ΄λ„ˆκ°€ μŠ€ν¬λ‘€λ˜λŠ” 것을 λ°©μ§€ν•˜λŠ” λ™μΌν•œ λ¬Έμ œμ— μ§λ©΄ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. λͺ¨λ“  ν•΄κ²° 방법은 κ½€ ν•΄ν‚€ν•˜κ³  기술적 뢀채λ₯Ό μΆ”κ°€ν•©λ‹ˆλ‹€.

λΆˆν–‰νžˆλ„ μˆ˜λ™μ μ΄μ§€ μ•Šμ€ μˆ˜μ‹ κΈ°κ°€ 있으면 μ‹€μ œλ‘œ μ—°κ²°λœ μ‚¬μš©μž μ˜μ—­ μ²˜λ¦¬κΈ°κ°€ 없더라도 μ‹¬κ°ν•œ 버벅거림이 λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€. Chrome은 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. (이것은 https://github.com/facebook/react/blob/92b7b172cce9958b846844f0b46fd7bbd8c5140d/packages/μ—μ„œ μΆ”κ°€ν•œ μ΅œμƒμœ„ μ²˜λ¦¬κΈ°μž…λ‹ˆλ‹€. react-dom/src/events/ReactDOMEventListener.js#L155)

@romulof @lencioni @radubrehar νŒ¨μ‹œλΈŒ ν”Œλž˜κ·Έκ°€ 슀크둀 이벀트 λ¦¬μŠ€λ„ˆμ—μ„œ μ‚¬μš©ν•˜κΈ° μœ„ν•œ 것이 μ•„λ‹ˆλΌλŠ” 사싀을 μ•Œκ³  κ³„μ‹­λ‹ˆκΉŒ? λΈŒλΌμš°μ €μ˜ 슀크둀 μ„±λŠ₯을 λ°©ν•΄ν•˜μ§€ μ•ŠμœΌλ €λ©΄ touchmove λ“±κ³Ό 같은 μ΄λ²€νŠΈμ— μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€. λ‹Ήμ‹ μ˜ μ˜ˆλŠ” λ‚˜μ—κ²Œ 맀우 ν˜Όλž€ μŠ€λŸ½μŠ΅λ‹ˆλ‹€.

κΈ°λ³Έ 슀크둀 μ΄λ²€νŠΈμ—μ„œλŠ” μˆ˜λ™ 섀정이 μ€‘μš”ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. μ·¨μ†Œν•  수 μ—†μœΌλ―€λ‘œ ν•΄λ‹Ή λ¦¬μŠ€λ„ˆκ°€ νŽ˜μ΄μ§€ λ Œλ”λ§μ„ 차단할 수 μ—†κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.

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

μΆ”κ°€ 정보: https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md

예, μ €λŠ” 이제 이것을 μ•Œκ³  μžˆμŠ΅λ‹ˆλ‹€. μ œκ°€ μ˜ˆμ „μ— 글을 썼을 λ•Œ 잘λͺ» μ•Œκ³  μžˆμ—ˆμ–΄μš”.
μ½”λ©˜νŠΈ. μ„€λͺ…ν•΄μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€!

2017λ…„ 12μ›” 6일 μˆ˜μš”μΌ, μ˜€μ „ 8:25 Martin Hofmann [email protected]
썼닀:

@romulof https://github.com/romulof @lencioni
https://github.com/lencioni @radubrehar https://github.com/radubrehar
μˆ˜λ™ ν”Œλž˜κ·Έκ°€
슀크둀 이벀트 λ¦¬μŠ€λ„ˆ? touchmove λ“±κ³Ό 같은 μ΄λ²€νŠΈμ— μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.
λΈŒλΌμš°μ €μ˜ 슀크둀 μ„±λŠ₯을 λ°©ν•΄ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. λ‹Ήμ‹ μ˜ 예
λ‚˜μ—κ²Œ 맀우 ν˜Όλž€ μŠ€λŸ½μŠ΅λ‹ˆλ‹€.

κΈ°λ³Έ 슀크둀 μ΄λ²€νŠΈμ—μ„œλŠ” μˆ˜λ™ 섀정이 μ€‘μš”ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
μ·¨μ†Œλ˜μ–΄ λ¦¬μŠ€λ„ˆκ°€ νŽ˜μ΄μ§€ λ Œλ”λ§μ„ 차단할 수 μ—†μŠ΅λ‹ˆλ‹€.

μ›μ²œ:
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Improving_scrolling_performance_with_passive_listeners

μΆ”κ°€ 정보:
https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md

β€”
당신이 μ–ΈκΈ‰λ˜μ—ˆκΈ° λ•Œλ¬Έμ— 이것을 λ°›λŠ” κ²ƒμž…λ‹ˆλ‹€.

이 이메일에 직접 λ‹΅μž₯ν•˜κ³  GitHubμ—μ„œ ν™•μΈν•˜μ„Έμš”.
https://github.com/facebook/react/issues/6436#issuecomment-349691618 ,
λ˜λŠ” μŠ€λ ˆλ“œ μŒμ†Œκ±°
https://github.com/notifications/unsubscribe-auth/AAL7zgbNCpHNui-TX7r2FYdhVxZfdBX8ks5s9r_4gaJpZM4ICWsW
.

@el-moalo-loco, μ„±λŠ₯ ν–₯상을 μœ„ν•΄ 슀크둀 μ΄λ²€νŠΈμ— μˆ˜λ™ λ¦¬μŠ€λ„ˆλ₯Ό μ‚¬μš©ν•˜λŠ” 방법에 λŒ€ν•΄ Google 개발자 μ‚¬μ΄νŠΈμ—μ„œ 일뢀 λ¬Έμ„œλ₯Ό μ½μ—ˆλ‹€κ³  ν™•μ‹ ν•©λ‹ˆλ‹€. λ‚΄κ°€ 잘λͺ» μ½μ—ˆκ±°λ‚˜ κ·Έ κ³Όμ •μ—μ„œ 무언가가 λ³€κ²½λ˜μ—ˆμ„ κ²ƒμž…λ‹ˆλ‹€. μ–΄μ¨Œλ“  λ§Žμ€ μ„€λͺ… κ°μ‚¬ν•©λ‹ˆλ‹€!

@romulof @lencioni @el-moalo-loco https://developers.google.com/web/tools/lighthouse/audits/passive-event-listeners
슀크둀 λ¦¬μŠ€λ„ˆκ°€ ν•„μš”ν•˜μ§€ μ•Šλ”λΌλ„ 휠 λ¦¬μŠ€λ„ˆλŠ” μ—¬μ „νžˆ μˆ˜λ™μ μ΄μ–΄μ•Ό ν•©λ‹ˆλ‹€. 그것이 ν˜Όλž€μ˜ 원인이 될 수 μžˆλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.

@sebmarkbage μ–΄λ–»κ²Œ μƒκ°ν•˜μ„Έμš”? 이 νŒ¨μ‹œλΈŒ 이벀트 λ¦¬μŠ€λ„ˆ 지원이 μ–Έμ  κ°€λŠ” React둜 λ“€μ–΄κ°ˆκΉŒμš”?

μ•ˆλ…•ν•˜μ„Έμš”,

λ‹€μŒκ³Ό 같이 componentDidMount 에 ν™œμ„± 이벀트 λ¦¬μŠ€λ„ˆλ₯Ό μΆ”κ°€ν•΄μ•Ό ν–ˆμŠ΅λ‹ˆλ‹€.

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

e.preventDefault() λ₯Ό ν˜ΈμΆœν•˜μ—¬ Chrome의 κΈ°λ³Έ μŠ€ν¬λ‘€μ„ μ€‘μ§€ν•˜κ³  touchStart() 의 μš”μ†Œλ₯Ό 이동할 수 μžˆμŠ΅λ‹ˆλ‹€.

μ–΄λ–€ μš”μ†Œλ₯Ό 이동해야 ν•˜λŠ”μ§€ μ•ŒκΈ° μœ„ν•΄ λ‹€μŒκ³Ό 같이 JSX μš”μ†Œμ— onTouchStart λ₯Ό μΆ”κ°€ν•΄μ•Ό ν–ˆμŠ΅λ‹ˆλ‹€.

onTouchStart={this.touchStartSetElement(element)}

touchStartSetElement() μ—μ„œ touchStart() μ—μ„œ 읽을 수 μžˆλŠ” μƒνƒœ 속성 element 을 μ„€μ •ν–ˆμŠ΅λ‹ˆλ‹€.

Reactκ°€ ν™œμ„± 이벀트 λ¦¬μŠ€λ„ˆλ₯Ό μ§€μ›ν•œλ‹€λ©΄ 이것은 ν•œ μ€„λ‘œ μš”μ•½λ  κ²ƒμž…λ‹ˆλ‹€.

감사 ν•΄μš”,

필립

μΆ”μ‹ : μˆ˜λ™ 이벀트 λ¦¬μŠ€λ„ˆμ—μ„œ e.preventDefault() λ₯Ό ν˜ΈμΆœν•˜λ €κ³  ν•˜λ©΄ Chrome 56μ—μ„œ λ‹€μŒ 였λ₯˜κ°€ λ°œμƒν•©λ‹ˆλ‹€.

[μ€‘μž¬] λŒ€μƒμ΄ μˆ˜λ™μœΌλ‘œ 처리되기 λ•Œλ¬Έμ— μˆ˜λ™ 이벀트 μˆ˜μ‹ κΈ° λ‚΄λΆ€μ—μ„œ Defaultλ₯Ό 방지할 수 μ—†μŠ΅λ‹ˆλ‹€. https://www.chromestatus.com/features/5093566007214080 μ°Έμ‘°

μˆ˜λ™ μ΄λ²€νŠΈλŠ” Google의 " κ°œμž… "으둜 인해 Chrome 56μ—μ„œ 기본이 λ˜μ—ˆκ³  μ–΄λ–»κ²Œλ“  웹을 깨뜨 λ Έμ§€λ§Œ 슀크둀 속도도 λΉ¨λΌμ‘ŒμŠ΅λ‹ˆλ‹€.

iOS 11.3의 Safari도 기본적으둜 μˆ˜λ™μœΌλ‘œ μ„€μ •λ˜μ–΄ 있고 touch-action:none 의 κΈ°μ‘΄ ν•΄κ²° 방법이 μ§€μ›λ˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— 이것은 더 λ§Žμ€ λ¬Έμ œκ°€ 되고

μ†Œν’ˆμ²˜λŸΌ μž‘λ™ν•˜λŠ” μ‚¬μš©μž μ •μ˜ μ°Έμ‘° ν•Έλ“€λŸ¬λ₯Ό 생성할 수 μžˆλŠ” RFC https://github.com/reactjs/rfcs/pull/28 을 μ œμ•ˆν–ˆμŠ΅λ‹ˆλ‹€(즉, onClick 와 같은 속성을 μ‚¬μš©ν•˜μ§€λ§Œ λŒ€μ‹  계산 속성 ꡬ문과 ν•Έλ“€λŸ¬λŠ” ref 및 prop κ°’ 정보 및 μ—…λ°μ΄νŠΈλ₯Ό κ°€μ Έμ˜΅λ‹ˆλ‹€. 이것듀은 당신이 가지고 μžˆλŠ” 거의 λͺ¨λ“  κ³ κΈ‰ μ‚¬μš© 사둀λ₯Ό μœ„ν•œ 라이브러리λ₯Ό λ§Œλ“œλŠ” 데 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

  • μˆ˜λ™μ , λͺ…μ‹œμ μœΌλ‘œ λΉ„μˆ˜λ™μ , ν•œ 번 및 이벀트 μΊ‘μ²˜λŠ” λͺ¨λ‘ μ‰½κ²Œ μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • 이벀트 ν•Έλ“€λŸ¬ 등둝보닀 훨씬 더 λ°œμ „λœ μž‘μ—…μ„ μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • μ‚¬μš©μžμ˜ κ΄€μ μ—μ„œ 보면 μ‚¬μš©ν•˜κΈ° 쉽고 λΌμ΄λΈŒλŸ¬λ¦¬μ—μ„œ μ œκ³΅ν•˜λŠ” 것을 λͺ¨λ“  μš”μ†Œμ— κ³„μ‚°λœ μ†μ„±μœΌλ‘œ μ „λ‹¬ν•˜κΈ°λ§Œ ν•˜λ©΄ λ©λ‹ˆλ‹€. 예: import {onScroll} from 'react-passive-events'; <div [onScroll]={scrollHandler} />

λ‚˜λŠ” 이것이 λͺ¨λ“  이벀트λ₯Ό 등둝 ν•˜λŠ” 방법이 λ˜μ–΄μ•Ό ν•œλ‹€κ³  μƒκ°ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

κ·ΈλŸ¬λ‚˜ κ°€λŠ₯ν•œ λͺ¨λ“  μœ ν˜•μ˜ 이벀트(캑처, μˆ˜λ™ λ“±...) 등둝을 μ²˜λ¦¬ν•˜λŠ” λ³΅μž‘ν•œ 방법을 μ°ΎλŠ” λŒ€μ‹  λŒ€λΆ€λΆ„μ˜ 이벀트(μˆ˜λ™ λ˜λŠ” λΉ„μˆ˜λ™)에 λŒ€ν•΄ κΈ°λ³Έ λ™μž‘μ΄ 무엇인지 κ²°μ •ν•˜κ³  μ΄λŸ¬ν•œ λ“±λ‘λœ 이벀트λ₯Ό μ‚¬μš©ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€. κ³ κΈ‰ μ‚¬μš© 사둀λ₯Ό μ²˜λ¦¬ν•˜λŠ” μ†Œν’ˆ.

λͺ¨λ“  ν„°μΉ˜ μ΄λ²€νŠΈλŠ” 이제 iOS 11.3μ—μ„œ 기본적으둜 μˆ˜λ™μž…λ‹ˆλ‹€. λ”°λΌμ„œ λͺ¨λ“  ν„°μΉ˜ 이벀트 ν•Έλ“€λŸ¬μ—μ„œ event.preventDefault()λ₯Ό ν˜ΈμΆœν•˜λŠ” 것은 이제 νš¨κ³Όκ°€ μ—†μŠ΅λ‹ˆλ‹€.

https://codesandbox.io/s/l4kpy569ol

λΉ„μˆ˜λ™ 이벀트 ν•Έλ“€λŸ¬λ₯Ό κ°•μ œν•  수 μ—†μœΌλ©΄ iOS 11.3 λ³€κ²½ 사항을 ν•΄κ²°ν•˜λŠ” 데 어렀움을 κ²ͺκ³  μžˆμŠ΅λ‹ˆλ‹€. https://github.com/atlassian/react-beautiful-dnd/issues/413

Vue.jsκ°€ 이것을 μ–΄λ–»κ²Œ μ²˜λ¦¬ν•˜λŠ”μ§€ μ•Œκ²Œ λ˜μ—ˆκ³  κ·Έλ“€μ˜ μ ‘κ·Ό 방식이 μƒλ‹Ήνžˆ λ§ˆμŒμ— λ“­λ‹ˆλ‹€.

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

μˆ˜μ •μž λͺ©λ‘μ€ λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

  • .λ©ˆμΆ”λ‹€
  • .μ˜ˆλ°©ν•˜λ‹€
  • .포착
  • .본인
  • .ν•œ 번
  • .μˆ˜λ™μ  인

μ›ν•˜λŠ” λ°©μ‹μœΌλ‘œ 이벀트λ₯Ό ꡬ성할 수 μžˆμŠ΅λ‹ˆλ‹€. μ•„λ§ˆλ„ 이것은 이 λ¬Έμ œμ— λŒ€ν•œ 영감으둜 도움이 될 수 μžˆμŠ΅λ‹ˆλ‹€.

@KeitIG μ €λŠ” React용으둜 μ„€κ³„λœ Vue-loader 포크λ₯Ό μž‘μ—… μ€‘μž…λ‹ˆλ‹€.

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

이건 λ‚  μŠ¬ν”„κ²Œ ν•΄

selection_028

이것이 이미 μ œμ•ˆλ˜μ—ˆλŠ”μ§€, μ•„λ‹ˆλ©΄ λ‚˜ μ΄μ™Έμ˜ λ‹€λ₯Έ μ‚¬λžŒμ—κ²Œ μ˜λ―Έκ°€ μžˆλŠ”μ§€ ν™•μ‹€ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

onTouchStart={listener} 

μ—κ²Œ

onTouchStart={listener, options}

λ‘˜ λ‹€ { passive, true, once: true } 와 같은 전달 μ˜΅μ…˜μ„ μžμ—°μŠ€λŸ¬μš΄ λ°©λ²•μœΌλ‘œ λ§Œλ“€κ³  addEventListener μŠ€ν‚€λ§ˆμ™€λ„ μΌμΉ˜ν•©λ‹ˆλ‹€.

@phaistonian 의 μ œμ•ˆμœΌλ‘œ μ΄λ™ν•˜λ©΄ ν˜„μž¬ μ‘΄μž¬ν•˜λŠ” onEventNameCapture ν•Έλ“€λŸ¬κ°€ ν•„μš”ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

@alexreardon 일반 jsμ—μ„œ listener, options λŠ” options ν‰κ°€λ˜λŠ” ν‘œν˜„μ‹μ΄λ―€λ‘œ μœ„μ˜ ꡬ성은 μ˜λ„ν•œ 것이 μ•„λ‹ˆκΈ° λ•Œλ¬Έμ— μ˜΅μ…˜μ΄ μ•„λ‹ˆλΌκ³  μƒκ°ν•©λ‹ˆλ‹€. 이λ₯Ό μœ„ν•΄μ„œλŠ” jsxκ°€ js둜 μ»΄νŒŒμΌλ˜λŠ” 방식을 λ³€κ²½ν•΄μ•Ό ν•˜λ©° μ΄λŠ” 획기적인 변경이 될 κ²ƒμž…λ‹ˆλ‹€. λ‚˜λŠ” λŒ€μ‘νŒ€μ΄ 이 길을 갈 것인지 μ˜μ‹¬μŠ€λŸ½λ‹€.

의견?

ν‘œν˜„μ΄λΌλŠ” μ μ—μ„œ 같은 μ˜λ„λ‘œ λ‹€λ₯΄κ²Œ ν•  수 μžˆλ‹€.

μ•„λ§ˆλ„ λ§Žμ€ μ˜΅μ…˜μ΄ μžˆμ„ κ²ƒμž…λ‹ˆλ‹€. μ˜΅μ…˜μ—λŠ” λ‹€μŒμ΄ ν¬ν•¨λ©λ‹ˆλ‹€.

import {handler} from 'React';

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

λ˜λŠ”

onTouchStart={[listener, options]}

λ˜λŠ”

onTouchStart={listener} onTouchStartOptions={options}

κ·Έλž˜λ„ 객체λ₯Ό μ „λ‹¬ν•œλ‹€λŠ” 아이디어가 κ°€μž₯ λ§ˆμŒμ— λ“­λ‹ˆλ‹€. μ–΄λŠ μͺ½μ΄λ“ , 이것은 해결책이 ν•„μš”ν•©λ‹ˆλ‹€.

아직 해결책이 μžˆμŠ΅λ‹ˆκΉŒ?

아직 해결책이 μžˆμŠ΅λ‹ˆκΉŒ?

각각 componentDidMount 및 componentWillUnmount addEventListener 및 removeEventListener componentWillUnmount μž…λ‹ˆλ‹€.

그래, μ§œμ¦λ‚œλ‹€.

그리고 후크λ₯Ό μ‚¬μš©ν•˜μ—¬ ν•΄κ²°ν•˜λŠ” 방법에 λŒ€ν•΄ μ–΄λ–»κ²Œ μƒκ°ν•˜μ‹­λ‹ˆκΉŒ?

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

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

@ara4n 후크λ₯Ό μ‚¬μš©ν•˜λŠ” 것은 μ’‹μ§€λ§Œ 후크가 μ•„λ‹Œ λ°˜μ‘μ— λŒ€ν•œ 고전적인 μ†”λ£¨μ…˜μ΄ μ—¬μ „νžˆ ν•„μš”ν•©λ‹ˆλ‹€.

@sebmarkbage 이에 λŒ€ν•œ μ—…λ°μ΄νŠΈκ°€ μžˆμŠ΅λ‹ˆκΉŒ? Chrome이 방금 λ°°μ†‘ν–ˆκ³  앱이 μ†μƒλ˜μ—ˆμŠ΅λ‹ˆλ‹€.

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
onWheel 이벀트 λ¦¬μŠ€λ„ˆμ—μ„œ κΈ°λ³Έ 슀크둀 λ™μž‘μ„ μ°¨λ‹¨ν•˜λ €κ³  ν•˜λ©΄ λ‹€μ‹œ λ°œμƒν•©λ‹ˆλ‹€.

@kychanbi 저와 λ™μΌν•˜μ§€λ§Œ Windows ν¬λ‘¬μ—μ„œλ§Œμ΄ 였λ₯˜κ°€ λ°œμƒν•©λ‹ˆλ‹€.

@kychanbi 였, λ¬Έμ„œ μˆ˜μ€€ Wheel/Mousewheel 이벀트 λ¦¬μŠ€λ„ˆλ₯Ό μˆ˜λ™μœΌλ‘œ μ²˜λ¦¬ν•˜λŠ” Chrome 73의 κΈ°λŠ₯μž…λ‹ˆλ‹€.

ꡬ성 μš”μ†Œ μ»¨ν…Œμ΄λ„ˆ div touch-action: μ—†μŒμ—μ„œ css 속성을 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

.μ»¨ν…Œμ΄λ„ˆ {
ν„°μΉ˜ μ•‘μ…˜: μ—†μŒ;
}

@madcher 마우슀 μ΄λ²€νŠΈμ—λŠ” μž‘λ™ν•˜μ§€ μ•ŠλŠ” 것 κ°™μŠ΅λ‹ˆλ‹€.
λ§ˆμΉ¨λ‚΄ λ„€μ΄ν‹°λΈŒ μžλ°” 슀크립트λ₯Ό μ‚¬μš©ν•˜μ—¬ ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€.
element.addEventListener("wheel", eventHandler);

이 λ¬Έμ œμ— μ§λ©΄ν•œ μ‚¬λžŒλ“€μ„ 돕기 μœ„ν•œ μž‘μ€ μŠ€λ‹ˆνŽ«:

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

μ—¬ν•˜νŠΌ onWheel μ†Œν’ˆμ΄ CSS touch-action: none; μž‘λ™ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

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

μ—¬μ „νžˆ 이 였λ₯˜κ°€ λ°œμƒν•©λ‹ˆλ‹€.
[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See <URL>

μž‘μ—… 버전

@markpradhan 의 후크 μ†”λ£¨μ…˜μ— λŒ€ν•œ λŒ€μ•ˆμœΌλ‘œ μ—¬μ „νžˆ ꡬ식 ꡬ성 μš”μ†Œλ₯Ό μ‚¬μš©ν•˜λŠ” 경우 λ‹€μŒμ„ μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

    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 μ•„λ§ˆλ„ # 14856 λ•Œλ¬ΈμΌ κ²ƒμž…λ‹ˆλ‹€.

이와 같은 것이 μ œμ•ˆλ˜μ—ˆμ§€λ§Œ 여기에 λͺ‡ 가지 아이디어가 더 μžˆμŠ΅λ‹ˆλ‹€.

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

이λ₯Ό 톡해 μ£Όμš” λ³€κ²½ 없이 μˆ˜λ™ 이벀트λ₯Ό μ‰½κ²Œ μ„ νƒν•˜κ±°λ‚˜ 이벀트λ₯Ό μΊ‘μ²˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ μ €λŠ” 기본적으둜 μˆ˜λ™ 이벀트 λ¦¬μŠ€λ„ˆλΌλŠ” 아이디어에 ν₯λ―Έλ₯Ό λŠκΌˆμŠ΅λ‹ˆλ‹€. λ‚˜λŠ” preventDefaultκ°€ μž‘μ—…μžμ—μ„œ Reactκ°€ μ‹€ν–‰λ˜λŠ” 것을 μ°¨λ‹¨ν•˜λŠ” μ£Όμš” μž₯μ• λ¬Ό(무엇보닀도)μ΄μ—ˆλ˜ 것을 κΈ°μ–΅ν•©λ‹ˆλ‹€.

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} />; }
이것이 μ£Όμš” λ³€κ²½ 사항이 λ˜μ§€ μ•Šλ„λ‘ 보μž₯ν•˜κΈ°λŠ” μ–΄λ €μšΈ κ²ƒμ΄μ§€λ§Œ, 이것이 μ‹œν–‰λœλ‹€λ©΄ μ΄λ²€νŠΈκ°€ preventDefault 이어야 ν•˜λŠ”μ§€ κ²°μ •ν•˜λŠ” λͺ¨λ“  μ½”λ“œκ°€ μ½”λ“œμ—μ„œ 격리되고 ReactλŠ” λ‹€μŒμ„ μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 메인 μŠ€λ ˆλ“œμ—μ„œ ν•΄λ‹Ή λΆ€λΆ„λ§Œ μ‹€ν–‰ν•˜κ³  λ‚˜λ¨Έμ§€λŠ” λ³„λ„μ˜ μž‘μ—…μž λ˜λŠ” λΉ„λ™κΈ°μ‹μœΌλ‘œ μ‹€ν–‰ν•©λ‹ˆλ‹€.

이 λ¬Έμ œκ°€ 해결될 λ•ŒκΉŒμ§€ event.preventDefault() λŒ€ν•œ μ°Έμ‘°κ°€ λ¬Έμ„œμ—μ„œ μ œκ±°λ˜κ±°λ‚˜ Chrome이 μˆ˜λ™ μ΄λ²€νŠΈμ—μ„œ preventDefault λ₯Ό ν•  수 μ—†λ‹€λŠ” κ²½κ³ κ°€ ν‘œμ‹œλ˜λŠ” 것이 κ°€μž₯ μ’‹μŠ΅λ‹ˆλ‹€.

React v17λΆ€ν„° 이벀트 μœ„μž„ λ³€κ²½μ˜ μ˜λ―Έκ°€ κΆκΈˆν•©λ‹ˆλ‹€. Lighthouseμ—λŠ” λΉ„μˆ˜λ™ μ΄λ²€νŠΈμ— λŒ€ν•΄ ν…ŒμŠ€νŠΈν•˜λŠ” https://web.dev/uses-passive-event-listeners/ κ·œμΉ™μ΄ μžˆμŠ΅λ‹ˆλ‹€.

μ΄μ „μ—λŠ” <div onTouchStart /> κ°€ λ¬Έμ„œμ— 등둝 λ˜μ—ˆμœΌλ©° 기본적으둜 μˆ˜λ™ μž…λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ React v17μ—μ„œλŠ” μ΄λ²€νŠΈκ°€ React 트리의 λ£¨νŠΈμ— λ“±λ‘λ˜λ―€λ‘œ νŠΉλ³„νžˆ μš”μ²­ν•˜μ§€ μ•ŠμœΌλ©΄ 더 이상 μˆ˜λ™μ μ΄μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

볡제: https://codesandbox.io/s/material-demo-forked-e2u72?file=/demo.js , 라이브: https://csb-e2u72.netlify.app/

Capture d’écran 2020-08-19 aΜ€ 16 11 31

응. μš°λ €λ˜λŠ” 것 κ°™μŠ΅λ‹ˆλ‹€. μƒˆλ‘œμš΄ 문제λ₯Ό μ œκΈ°ν•˜κ² μŠ΅λ‹ˆλ‹€.

React 17 토둠을 μœ„ν•΄ https://github.com/facebook/react/issues/19651 에 μ œμΆœν–ˆμŠ΅λ‹ˆλ‹€.

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰