https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md
ããã©ã«ãã§ãã¹ãŠãããã·ãã«ããå¿ èŠãªå Žåã«ã®ã¿ã¢ã¯ãã£ãã«ãªããã€ã³ããããšããå§ãããŸãã ããšãã°ãããã¹ãå ¥åã€ãã³ãããªãã¹ã³ããããšã¯ã§ããŸãããã¢ã¯ãã£ããªãªã¹ããŒãããå Žåã¯ãpreventDefaultãŸãã¯äœ¿çšãããå¶åŸ¡ãããåäœã®ã¿ãå¯èœã§ãã
åæ§ã«ããããReactNativeã®ã¹ã¬ããã¢ãã«ãšçµ±åããããšãã§ããŸãã ããšãã°ãããŒã¹ãããŒã¯ã®åŠçãªã©ãã¢ã¯ãã£ããªãªã¹ããŒãããå Žåã«UIã¹ã¬ãããåæçã«ãããã¯ããããšãã§ããŸãã
cc @vjeux @ide
ããã¯Chrome51ã«å°å ¥ãããŸãããReactã§ããããµããŒãããããã®æŽæ°ãããèšç»ã¯ãããŸããïŒ ïŒO
Reactã®ããã¥ã¡ã³ãã«ã€ãã³ããªã¹ããŒã1ã€ãããªããä»ã®ãªã¹ããŒã«å§ä»»ããå Žåãããã¯ã©ã®ããã«å¯èœã§ããïŒ
@sebmarkbage
ããã·ãã€ãã³ãã®åé¡ã®çŸåšã®ã¹ããŒã¿ã¹ã¯äœã§ããïŒ
ãã€ãŒã«ã€ãã³ãã®åŠçã«ã€ããŠChromeã§èŠåã衚瀺ãããŸãããããã¯ãããã·ãã€ãã³ããã³ãã©ãŒãšããŠç»é²ãããŠããå Žåã«æé©åã§ããŸãã ã ããããããReactã«å ¥ããã®ã¯ããããšã ããïŒ
FWIWãFacebookã¯ã¢ã¯ãã£ããªãã€ãŒã«ã€ãã³ãããªãã¹ã³ããŠããµã€ãããŒãŸãã¯ãã£ãããŠã£ã³ããŠãã¹ã¯ããŒã«ããããšãã«å€åŽã®ã¹ã¯ããŒã«ããããã¯ããŸãã ãããªãã§ã¯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ã®ææ¡ãšçµã¿åããããšãããã¯ããããããã»ã©é¢åã§ã¯ãªãã§ãããã
é ã«æµ®ãã¶ãã1ã€ã®ã¢ãããŒãã¯ãããããã£ãã€ãã³ããã³ãã©ãŒã«ã¢ã¿ããããŠãããã·ãã¢ãŒãããªããã¢ãŠãã§ããããã«ããïŒãŸãã¯ä»ã®ãªãã·ã§ã³ãåãæ¿ããïŒããšã§ãã ãã®ãããªãã®ïŒ
class Foo extends React.Component {
constructor() {
this.handleScroll = this.handleScroll.bind(this);
this.handleScroll.passive = false;
}
handleScroll() {
...
}
render() {
return <div onScroll={this.handleScroll} />;
}
}
çè«çã«ã¯ããã³ã¬ãŒã¿ãçå°ãããšãããã¯ãã³ã¬ãŒã¿ã§éåžžã«ããŸãæ©èœããŸãã
ããã«ã€ããŠããå°ãèããŠã¿ããšãåã ã®ãªãã·ã§ã³ã§ã¯ãªããã€ãã³ããªãã·ã§ã³ããããã£ãé¢æ°ã«è¿œå ããæ¹ããããšæããŸãã ããã«ãããReactã¯ãæœåšçã«å€ãã®ããããã£ã§ã¯ãªãã1ã€ã®ããããã£ã«ã€ããŠã®ã¿å¿é ããå¿ èŠããããŸãã ãããã£ãŠãäžèšã®äŸã調æŽããã«ã¯ã次ã®ããã«ããŸãã
class Foo extends React.Component {
constructor() {
this.handleScroll = this.handleScroll.bind(this);
this.handleScroll.options = { passive: false };
}
handleScroll() {
...
}
render() {
return <div onScroll={this.handleScroll} />;
}
}
ç§ãæãã€ãããã1ã€ã®èãã¯ããããã®ãªãã·ã§ã³ã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ãã³ãã©ãŒã«ã¯ããã€ãã£ãã€ãã³ãã«äŒŒãŠããŸãããç°ãªããåæã€ãã³ãããæž¡ãããŸãã ã¡ãªã¿ã«ãç§ã¯å®éã«ãããè¡ãã³ãŒããèªãã§ããªãã®ã§ãããå€ãã®ç¥èãæã£ãŠãã人ãç§ãèšãããšããŠããããšãèšæ£ããå¿ èŠããããŸãã
ç§ã¯å®è£
ã®è©³çŽ°ã«ããŸã粟éããŠããŸãããã preventDefault
ã¯ãå°ãªããšã_é²æ¢ããŠãããã³ãã©ãŒãReactã€ãã³ããã³ãã©ãŒã§ãããéã_æ©èœããããšãç¥ã£ãŠããŸãã ãšã«ãããããã¯ç§ã®çµéšã§ãã
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æè¿ã
https://www.chromestatus.com/features/5093566007214080ãåç §ããŠ
ããã«ãããReactã®åäœæ¹æ³ãéæ¥çã«å€æŽãããŸãã-ã€ãã³ããã¢ã¿ãããããšãã«Reactãpassive: false
ã«ã€ããŠæ瀺çã«èšåããŠããªããšæããŸã-ãããã£ãŠãåäœãå€æŽãããŸããã
ç§ãããããããããŸãã-ãããã£ãŠãaddEventListenerã䜿çšããŠã¿ããã€ãã³ããæåã§ç»é²ããå¿ èŠããããŸã
ã¯ããŒã ããã·ãã»ãã€ã»ããã©ã«ãä»å
¥ã®ã¿ã«é©çšãããããšã«æ³šætouchstart
ãštouchmove
ã§ã¯ãªãã wheel
ã ãããã£ãŠãæ瀺çãª{passive: true}
ãªãwheel
ã€ãã³ãã¯ãããŠã¹ãã€ãŒã«ãš2æ¬æã®ãã©ãã¯ãããã¹ã¯ããŒã«ã®å Žåã§ããåæã¹ã¯ããŒã«ã匷å¶ããŸãã ïŒç§ã¯ããã«ããã€ãã®åŸ®åŠãªç¹ã«ã€ããŠã®ããã°æçš¿ãæžããŸãããïŒ
ãŸããç§ãã¡ïŒEdgeããŒã ïŒã¯åãä»å
¥ãå®è£
ããã€ããã¯ãªãã®ã§ãããã·ãã€ãã³ããªã¹ããŒãåºè·ãããšãã¯ã {passive: true}
ãæ瀺çã«æå®ããå¿
èŠããããŸãã
åèãŸã§ã«ãç§ã¯ããã·ãïŒfalseãã¹ãäžãå§ããã¹ã¯ããŒã«divããããšãã«ã¢ãã€ã«ã§æ¬äœãã¹ã¯ããŒã«ããªãããã«ããŸããããpreventDefaultïŒïŒã䜿çšããŠã¹ã¯ããŒã«ããããã¯ããã®ã¯å°ãéãã§ãã divãååšãããã©ããã«å¿ããŠãã³ãã©ãŒãè¿œå ããã³åé€ããããbody.height = 100ïŒ ã¢ãããŒãã«ãã©ãŒã«ããã¯ããããšãã§ããŸãã body.heightã®ä¿®æ£ã¯å°ãããããŒãªæããããŸãããããã·ãã¯å¿ èŠãããŸãããfalseã§ãã
ç§ã®ãŠãŒã¹ã±ãŒã¹ã§ã¯ã event.preventDefault()
ã¡ãœããã䜿çšããŠããŠãŒã¶ãŒãèŠçŽ ãã³ã³ããå
ã«ãã©ãã°ããŠãããšãã«ã³ã³ãããã¹ã¯ããŒã«ããªãããã«ããŸãã
ãã®ããã«ã¯ãã€ãã³ããªã¹ããŒãéããã·ãïŒããã·ãïŒfalseïŒãšããŠç»é²ããå¿
èŠããããŸãã
ãã©ãŠã¶ãããã·ãã«åãæ¿ãã£ãŠããã®ã§ïŒããã©ã«ãã§ã¯trueã§ãããå察ã®ããšãã§ããããã«ããããšæããŸã
æ®å¿µãªããã touch-action: none;
ã¹ã¿ã€ã«ã¯ã¿ããéå§åŸã«é©çšãããŠããããã䜿çšã§ããŸããããããããããå¹æããªãçç±ã§ãã
ããã¯ç¢ºãã«ããã«åé¡ã«ãªãã§ããããç§ã¯2幎ã§è§£æ±ºçãèŠã€ãããªãã£ãããšã«é©ããŠããŸãã ãŸããã€ãã³ããªã¹ããŒãæåã§äœæããããšã¯ãReactã®ã¢ã³ããã¿ãŒã³ã§ãã
ãããŠããããé倧ãªå€åãçã¿åºãã®ã§ããã°ããããªãã§ãããã ããããç§ã¯ç©èªã®äžéšãèŠéããŠãããããããŸããã
ç§ã«@romulofã«ãã£ãŠææ¡ãããæ°ããã€ãã³ããªã¹ã眲åãªã©ã®https://github.com/facebook/react/issues/6436#issuecomment -254331351ã
ããã§èª¬æããåé¡ã®ä¿®æ£ã«å ããŠã 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 ïŒ
è¿œå æ å ±ïŒ https ïŒ
ã¯ããç§ã¯ä»ããã«æ°ã¥ããŠããŸãã 以åã«æžãããšãã«èª€è§£ãããŸãã
ã³ã¡ã³ãã æ確ã«ããŠãããŠããããšãïŒ
æ°Žææ¥ã2017幎12æ6æ¥ã«ã¯ã8:25ããŒãã£ã³ã»ãããã³[email protected]
æžããŸããïŒ
@romulof https://github.com/romulof @lencioni
https://github.com/lencioni @radubrehar https://github.com/radubrehar
ããã·ããã©ã°ã¯ã§ã®äœ¿çšãç®çãšããŠããªããšããäºå®ãç¥ã£ãŠããŸãã
ã¹ã¯ããŒã«ã€ãã³ããªã¹ããŒïŒ touchmoveãªã©ã®ã€ãã³ãã§äœ¿çšããå¿ èŠããããŸãã
ãã©ãŠã¶ã®ã¹ã¯ããŒã«ããã©ãŒãã³ã¹ã劚ããªãããã«ããŸãã ããªãã®äŸ
ç§ã«ã¯éåžžã«æ··ä¹±ããŠããŸããããã·ãã®èšå®ã¯ãåºæ¬çãªã¹ã¯ããŒã«ã€ãã³ãã§ã¯éèŠã§ã¯ãããŸããã
ãã£ã³ã»ã«ãããããããªã¹ããŒã¯ããŒãžã®ã¬ã³ããªã³ã°ããããã¯ã§ããŸãããè¿œå æ å ±ïŒ
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ãããã©ãŒãã³ã¹ãåäžãããããã«ã¹ã¯ããŒã«ã€ãã³ãã«ããã·ããªã¹ããŒã䜿çšããããšã«ã€ããŠãGoogleDevelopersãµã€ãã®ããã€ãã®ããã¥ã¡ã³ããèªãã ããšã¯ééããããŸããã éäžã§èªã¿ééããããäœããå€ãã£ãã«éããããŸããã ãšã«ããã説æããŠãããŠããããšãïŒ
@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
touchStartSetElement()
ãèšå®ããŸãã
Reactãã¢ã¯ãã£ããªã€ãã³ããªã¹ããŒããµããŒãããå Žåãããã¯1è¡ã«èŠçŽãããŸãã
ããããšãã
ãã£ãªãã
PSïŒããã·ãã€ãã³ããªã¹ããŒã§e.preventDefault()
ãåŒã³åºãããšãããšãChrome56ã§æ¬¡ã®ãšã©ãŒãçºçããŸãã
[ä»å ¥]ã¿ãŒã²ãããããã·ããšããŠæ±ããããããããã·ãã€ãã³ããªã¹ããŒå ã®Defaultãé²ãããšãã§ããŸããã https://www.chromestatus.com/features/5093566007214080ãåç §ããŠ
ããã·ãã€ãã³ãã¯ãGoogleã®ãä»å ¥ããšäœããã®åœ¢ã§ãŠã§ãã
iOS 11.3以éã®Safariãããã©ã«ãã§ããã·ãã«èšå®ãããŠããã touch-action:none
ã®åŸæ¥ã®åé¿çã¯ãµããŒããããŠããªããããããã¯ããã«åé¡ã«ãªãã€ã€
å°éå
·ã®ããã«æ©èœããã«ã¹ã¿ã åç
§ãã³ãã©ãŒãäœæã§ããRFChttps ïŒ//github.com/reactjs/rfcs/pull/28ãææ¡ããŸããïŒã€ãŸãã onClick
ããã«ããããã£ã䜿çšããŸããã代ããã«èšç®ã䜿çšããŸãããããã£æ§æãšãã³ãã©ãŒã¯ãrefãšpropã®å€ã®æ
å ±ãšæŽæ°ãååŸããŸãïŒã ãããã¯ããæã¡ã®ã»ãŒãã¹ãŠã®é«åºŠãªãŠãŒã¹ã±ãŒã¹ã®ã©ã€ãã©ãªãäœæããããã«äœ¿çšã§ããŸãã
import {onScroll} from 'react-passive-events';
<div [onScroll]={scrollHandler} />
ãããããã¹ãŠã®ã€ãã³ããç»é²ããæ¹æ³ã§ããã¹ãã§ã¯ãªããšæããŸãã
ãã ããèãããããã¹ãŠã®ã¿ã€ãã®ã€ãã³ãïŒãã£ããã£ãããã·ããªã©ïŒã®ç»é²ãåŠçããè€éãªæ¹æ³ãèãåºã代ããã«ãã»ãšãã©ã®ã€ãã³ãïŒããã·ããŸãã¯éããã·ãïŒã®ããã©ã«ãã®åäœã決å®ãããããã®ç»é²æžã¿ã䜿çšããããšããå§ãããŸãããé«åºŠãªãŠãŒã¹ã±ãŒã¹ãåŠçããããã®å°éå ·ã
iOS 11.3ã§ã¯ããã¹ãŠã®ã¿ããã€ãã³ããããã©ã«ãã§ããã·ãã«ãªããŸããã ãããã£ãŠãã¿ããã€ãã³ããã³ãã©ãŒã§event.preventDefaultïŒïŒãåŒã³åºããšãå¹æããªããªããŸãð¢
éããã·ãã€ãã³ããã³ãã©ãŒã匷å¶ããããšãã§ããªããã°ãiOS11.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ããŒããŒã®ãã©ãŒã¯ã«åãçµãã§ããŸã
ããã¯ç§ãæ²ãããããŸã
ããããã§ã«ææ¡ãããŠãããã©ããããŸãã¯ç§ä»¥å€ã®èª°ãã«ãšã£ãŠæå³ããããã©ããã¯ããããŸãããã次ã®ããã«ãªããŸãã
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}
ç§ã¯ãªããžã§ã¯ããæž¡ããšããã¢ã€ãã¢ãäžçªå¥œãã§ãã ãããã«ãããããã«ã¯è§£æ±ºçãå¿ èŠã§ãã
ãŸã 解決çã¯ãããŸããïŒ
ãŸã 解決çã¯ãããŸããïŒ
ããªãã®å€å
žçãªaddEventListener
ãšremoveEventListener
ã¯ããããcomponentDidMount
ãšcomponentWillUnmount
ãŸãã
ãããããã¯ææªã ã
ãããŠãããã¯ã䜿ã£ãŠããã解決ããããã«ããªãã¯ã©ãæããŸããïŒ
...
const onClickPassive = useEventListener((e) =>Â {
console.log('passive event')
}, { passive: true })
return (
<button onClick={onClickPassive}>Click me</button>
)
@ ara4nã¯ããã¯ã䜿çšããã®ãè¯ãã§ãããããã¯ä»¥å€ã®åå¿ã®ããã®å€å žçãªè§£æ±ºçããŸã å¿ èŠã§ã
@sebmarkbageããã«é¢ããæŽæ°ã¯ãããŸããïŒ Chromeã¯ãããåºè·ããã°ããã§ãã¢ããªãå£ããŸããã
[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See https://www.chromestatus.com/features/6662647093133312
onWheel
ã€ãã³ããªã¹ããŒã§ããã©ã«ãã®ã¹ã¯ããŒã«åäœããããã¯ããããšãããšãåã³çºçããŸã
@kychanbiç§ãšåãã§ããããã®ãšã©ãŒã¯
@kychanbiãããããã¯ããã¥ã¡ã³ãã¬ãã«ã®Wheel / Mousewheelã€ãã³ããªã¹ããŒãããã·ããšããŠæ±ã
ã³ã³ããŒãã³ãã³ã³ããã§cssããããã£ã䜿çšã§ããŸãdivtouch-actionïŒnone
ãå®¹åš {
ã¿ããã¢ã¯ã·ã§ã³ïŒãªã;
}
@madcherããŠã¹ã€ãã³ãã§ã¯æ©èœããªãããã§ãã
ç§ã¯ã€ãã«ãã€ãã£ãJavaScriptã䜿çšããŠããã解決ããŸãã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
edããå¿
èŠããããã©ãããå€æãããã¹ãŠã®ã³ãŒããã³ãŒãã«åé¢ãããReactã¯æ¬¡ã®ããšãã§ããããã«ãªããŸãããã®éšåã ããã¡ã€ã³ã¹ã¬ããã§å®è¡ããä»ã®ãã¹ãŠãå¥ã®ã¯ãŒã«ãŒã§ããŸãã¯éåæã§å®è¡ããŸãã
ããã解決ããããŸã§ã event.preventDefault()
ãžã®åç
§ãããã¥ã¡ã³ãããåé€ãããããå°ãªããšãããã·ãã€ãã³ãã§ChromeãpreventDefault
ã䜿çšã§ããªãããšã«é¢ããèŠåã衚瀺ãããŠãããšãããšæããŸãã
Reactv17ããã®ã€ãã³ãå§ä»»ã®å€æŽã®åœ±é¿ã«ã€ããŠçåã«æããŸãã Lighthouseã«ã¯ãéããã·ãã€ãã³ãã«å¯ŸããŠãã¹ãããã«ãŒã«https://web.dev/uses-passive-event-listeners/ããããŸãã
以åã¯ã <div onTouchStart />
ãããã¥ã¡ã³ãã«ç»é²ãããŠããŸããããããã¯ããã·ãã§ãã ãã ããReact v17ã§ã¯ãã€ãã³ãã¯ReactããªãŒã®ã«ãŒãã«ç»é²ãããŸããReactããªãŒã¯ãç¹ã«èŠæ±ããªãéãããã·ãã§ã¯ãªããªããŸãã
ããã æžå¿µããŠããããã§ãã æ°ããåé¡ãæåºããŸãã
React17ã®è°è«ã®ããã«https://github.com/facebook/react/issues/19651ãæåºããŸããã
æãåèã«ãªãã³ã¡ã³ã
ãã€ãŒã«ã€ãã³ãã®åŠçã«ã€ããŠChromeã§èŠåã衚瀺ãããŸãããããã¯ãããã·ãã€ãã³ããã³ãã©ãŒãšããŠç»é²ãããŠããå Žåã«æé©åã§ããŸãã ã ããããããReactã«å ¥ããã®ã¯ããããšã ããïŒ