Skip to content

Commit 51b78c9

Browse files
authored
Merge pull request #186 from janczizikow/feat/passive-event-listeners
feat: support passive event listeners
2 parents d6d54c8 + 3f1b2f5 commit 51b78c9

File tree

2 files changed

+94
-9
lines changed

2 files changed

+94
-9
lines changed

src/index.js

+68-9
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types'
33
import shallowequal from 'shallowequal'
44
import raf from 'raf'
55
import shouldUpdate from './shouldUpdate'
6+
import supportsPassiveEvents from './supportsPassiveEvents'
67

78
const noop = () => {}
89

@@ -58,6 +59,7 @@ export default class Headroom extends Component {
5859
this.lastKnownScrollY = 0
5960
this.scrollTicking = false
6061
this.resizeTicking = false
62+
this.eventListenerOptions = false
6163
this.state = {
6264
state: 'unfixed',
6365
translateY: 0,
@@ -67,11 +69,28 @@ export default class Headroom extends Component {
6769

6870
componentDidMount () {
6971
this.setHeightOffset()
72+
73+
this.eventListenerOptions = supportsPassiveEvents()
74+
? { passive: true, capture: false }
75+
: false
76+
7077
if (!this.props.disable) {
71-
this.props.parent().addEventListener('scroll', this.handleScroll)
78+
this.props
79+
.parent()
80+
.addEventListener(
81+
'scroll',
82+
this.handleScroll,
83+
this.eventListenerOptions
84+
)
7285

7386
if (this.props.calcHeightOnResize) {
74-
this.props.parent().addEventListener('resize', this.handleResize)
87+
this.props
88+
.parent()
89+
.addEventListener(
90+
'resize',
91+
this.handleResize,
92+
this.eventListenerOptions
93+
)
7594
}
7695
}
7796
}
@@ -91,27 +110,67 @@ export default class Headroom extends Component {
91110

92111
// Add/remove event listeners when re-enabled/disabled
93112
if (!prevProps.disable && this.props.disable) {
94-
this.props.parent().removeEventListener('scroll', this.handleScroll)
95-
this.props.parent().removeEventListener('resize', this.handleResize)
113+
this.props
114+
.parent()
115+
.removeEventListener(
116+
'scroll',
117+
this.handleScroll,
118+
this.eventListenerOptions
119+
)
120+
this.props
121+
.parent()
122+
.removeEventListener(
123+
'resize',
124+
this.handleResize,
125+
this.eventListenerOptions
126+
)
96127

97128
if (prevState.state !== 'unfixed' && this.state.state === 'unfixed') {
98129
this.props.onUnfix()
99130
}
100131
} else if (prevProps.disable && !this.props.disable) {
101-
this.props.parent().addEventListener('scroll', this.handleScroll)
132+
this.props
133+
.parent()
134+
.addEventListener(
135+
'scroll',
136+
this.handleScroll,
137+
this.eventListenerOptions
138+
)
102139

103140
if (this.props.calcHeightOnResize) {
104-
this.props.parent().addEventListener('resize', this.handleResize)
141+
this.props
142+
.parent()
143+
.addEventListener(
144+
'resize',
145+
this.handleResize,
146+
this.eventListenerOptions
147+
)
105148
}
106149
}
107150
}
108151

109152
componentWillUnmount () {
110153
if (this.props.parent()) {
111-
this.props.parent().removeEventListener('scroll', this.handleScroll)
112-
this.props.parent().removeEventListener('resize', this.handleResize)
154+
this.props
155+
.parent()
156+
.removeEventListener(
157+
'scroll',
158+
this.handleScroll,
159+
this.eventListenerOptions
160+
)
161+
this.props
162+
.parent()
163+
.removeEventListener(
164+
'resize',
165+
this.handleResize,
166+
this.eventListenerOptions
167+
)
113168
}
114-
window.removeEventListener('scroll', this.handleScroll)
169+
window.removeEventListener(
170+
'scroll',
171+
this.handleScroll,
172+
this.eventListenerOptions
173+
)
115174
}
116175

117176
setRef = ref => (this.inner = ref)

src/supportsPassiveEvents.js

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* Used to detect browser support for adding an event listener with options
3+
* @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Improving_scrolling_performance_with_passive_listeners
4+
* @returns Boolean
5+
*/
6+
export default function supportsPassiveEvents () {
7+
let passiveSupported = false
8+
9+
try {
10+
const options = {
11+
get passive () {
12+
// This function will be called when the browser
13+
// attempts to access the passive property.
14+
passiveSupported = true
15+
return false
16+
},
17+
}
18+
19+
window.addEventListener('test', null, options)
20+
window.removeEventListener('test', null, options)
21+
} catch (err) {
22+
passiveSupported = false
23+
}
24+
25+
return passiveSupported
26+
}

0 commit comments

Comments
 (0)