Vue Scroll locked mixin
by ChangJoo Park
HTML
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<div id="app">
<div class="outer-container">
<something></something>
<something></something>
<something></something>
<div class="scroll-locked inner-container">
<h1>Hello</h1>
<h1>Hello</h1>
<h1>Hello</h1>
<h1>Hello</h1>
<h1>Hello</h1>
<h1>Hello</h1>
<h1>Hello</h1>
<h1>Hello</h1>
<h1>Hello</h1>
</div>
<div class="scroll-locked inner-container">
<h1>Hello</h1>
<h1>Hello</h1>
<h1>Hello</h1>
<h1>Hello</h1>
<h1>Hello</h1>
<h1>Hello</h1>
<h1>Hello</h1>
<h1>Hello</h1>
<h1>Hello</h1>
</div>
</div>
</div>
<template id="something">
<div class="something-outer scroll-locked">
<div class="something-inner">
<h1>Component</h1>
<h1>Component</h1>
<h1>Component</h1>
<h1>Component</h1>
<h1>Component</h1>
<h1>Component</h1>
<h1>Component</h1>
<h1>Component</h1>
<h1>Component</h1>
</div>
</div>
</template>
CSS
#app {
background-color: tomato;
overflow: scroll;
}
.outer-container {
width: 100vw;
height: 200vh;
}
.inner-container {
width: 300px;
height: 300px;
margin: 0 auto;
margin-top: 100px;
background-color: white;
overflow: auto;
}
.something-outer {
width: 300px;
height: 300px;
background-color: white;
overflow: scroll;
display: inline-block;
}
JavaScript
var scrollLockMixin = {
mounted: function() {
var scrollables = this.$el.querySelectorAll('.scroll-locked');
if (scrollables && scrollables.length > 0) {
scrollables.forEach(function(scrollable) {
scrollable.addEventListener('wheel', function(event) {
var meetTop = scrollable.scrollTop === 0;
var meetBottom = (scrollable.scrollHeight - scrollable.clientHeight) === scrollable.scrollTop;
var isUpward = event.deltaY < 0;
var isDownward = event.deltaY > 0;
if (meetBottom && isDownward) {
event.preventDefault();
event.stopPropagation();
return;
}
if (meetTop && isUpward) {
event.preventDefault();
event.stopPropagation();
return;
}
});
})
}
},
beforeDestroyed: function() {
var scrollables = this.$el.querySelectorAll('.scroll-lockable');
if (scrollables && scrollables.length > 0) {
scrollables.forEach(function(scrollable) {
scrollable.removeEventListener('wheel');
})
}
}
};
Vue.component('something', {
template: '#something',
mixins: [scrollLockMixin]
})
new Vue({
el: '#app',
mixins: [scrollLockMixin]
})