How to unbind an event while jump to other page in NUXTjs? - javascript

I have written this code in one page. It works but how can I unbind this event when i Jump to other page?
private mounted () {
if (process.browser) {
const banner:any = document.querySelector('.banner img')
document.addEventListener('scroll', () => {
const offsetTop = window.scrollY
const INTOR_HEIGHT = document.querySelector('.intro-text').offsetHeight
if (offsetTop < INTOR_HEIGHT) {
banner.style.top = offsetTop + 'px'
}
})
}
}
when I jump to other page form this page,this error is thrown:
javascript Uncaught TypeError: Cannot read property 'offsetHeight' of
null
at HTMLDocument.eval

haha , VUE.js Instance Lifecycle Hooks also can use in nuxt.js.
so just like this
private smoothSlier () {
const banner:any = document.querySelector('.banner img')
const offsetTop = window.scrollY
const INTOR_HEIGHT:any = document.querySelector('.intro-text').offsetHeight
if (offsetTop < INTOR_HEIGHT) {
banner.style.top = offsetTop + 'px'
}
}
private mounted () {
if (process.browser) {
document.addEventListener('scroll', this.smoothSlier)
}
}
private beforeDestroy () {
document.removeEventListener('scroll', this.smoothSlier)
}
the point is bind golbal event in mounted hooks and,unbind in beforeDestroy

Related

Change position fixed of div if scroll

I tried to fix a div after scroll on vuejs; My code like this :
...
async created() {
window.addEventListener('scroll', this.calendarScroll);
}
methods: {
calendarScroll() {
console.log('Scroll');
const dateHeader = document.querySelector('.dates-header');
if (dateHeader) {
if (window.scrollTop() >= 200) {
dateHeader.style.top = 0;
dateHeader.style.position = 'fixed';
}
}
},
}
the error is : Calendar.vue?404a:681 Uncaught TypeError: window.scrollTop is not a function
You can add scrollTo to the Element prototype before you mount:
Element.prototype.scrollTo = () => {}
All Elements created after you add this code will have the scrollTo method.
For more detail, you can check this: https://github.com/vuejs/vue-test-utils/issues/319#issuecomment-354667621

Window.scroll only working once (React.js)

I'm making a simple React component to remember where you are on the page and place you there when returning.
Here's the code:
function ScrollCache() {
window.scroll(0, parseInt(localStorage['scroll']));
document.addEventListener('scroll', function (e) {
if (window.scrollY != 0) {
localStorage['scroll'] = window.scrollY.toString();
}
})
return (<></>)
}
Basically, it caches the last known scroll position, and uses window.scroll(x, y) to scroll to that position. I have verified that localStorage is working as intended with a console.log immediately before the window.scroll. I've also just tried a static 100 for the y coordinate. No matter what, it only scrolls once at reload and then never again when I'm navigating around.
I'm using React Router to go between web pages. Any help is appreciated
You don't need to add the scroll event listener every time you want to cache the scroll.
Instead, try this:
const [scrollPosition, setScrollPosition] = useState(0);
useEffect(() => {
window.addEventListener("scroll", handleScroll, {
passive: true
});
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, [scrollPosition]);
useEffect(() => {
localStorage['scroll'] = scrollPosition.toString();
}, [scrollPosition);
const handleScroll = () => {
const position = window.pageYOffset;
setScrollPosition(position);
};

Scroll event runs even though i have not scrolled

The console logs this sentence 'hello' immediately after i refresh the page even though i have not scrolled on my mouse.
const changeOpacity = () => {
window.onscroll = console.log('hello')}
changeOpacity();
window.onscroll = console.log('hello') - will immediately invoke the call to console.log
You should wrap the assignment in a function declaration, like this:
window.onscroll = () => { console.log('hello'); }
This way your function will be called each time a scroll event is detected. Here's an example of how this would work:
const changeOpacity = () => {
window.onscroll = e => { console.log(`hello ${e.detail}`); };
}
//Init the event handler
changeOpacity();
//Fire some scroll events to test our handler
for(let i = 0; i < 10; i += 1) {
window.dispatchEvent(new CustomEvent('scroll', { detail: `scroll event ${i}` }));
}

Removing eventHandler in function called by addEventListener

I added an infinite scrolling feature to my page. It attaches an event listener in the componentDidMount lifecycle hook and I want to remove it within the action called by the event listener when there is no "nextlink anymore". I set a console.log() message which works fine, but I am uncertain why the window.removeEventListener() function does not work. Any help would be appreciated.
Piece of code responsible for adding/removing the eventListener.
componentDidMount() {
this._isMounted = true;
this.props.onFetchTeams();
this.scrollListener = window.addEventListener("scroll", e => {
this.handleScroll(e);
});
}
handleScroll = () => {
const hasMoreLink = this.props.teams["#odata.nextLink"];
if (hasMoreLink == "") {
console.log("remove event handler");
window.removeEventListener("scroll", this.handleScroll);
}
// If there is at least a team and is currently not loading, proceed to load more.
if (this.state.loadingMore === false && this.props.teams["value"]) {
// get the last teamcard in the page
const lastTeam = document.querySelector(
".team-card-wrapper:last-of-type"
);
// get the height of the current team, and get the height of the current position on screen.
const lastTeamOffset = lastTeam.offsetTop + lastTeam.clientHeight;
const pageOffset = window.pageYOffset + window.innerHeight;
// the range that teams will load earlier than the bottom of the page.
const bottomOffset = 30;
if (pageOffset > lastTeamOffset - bottomOffset) {
this.setState({ loadingMore: true });
this.props.onFetchMoreTeams(hasMoreLink);
}
}
};
removeListener needs the same reference for function that it used while addListener. Change the code to addEventListener like
this.scrollListener = window.addEventListener("scroll", this.handleScroll);
This is because the function that is given to addEventListener and the one given to the removeEventListener should be exactly the same, but in your case, you are creating a new arrow function for the addEventListener. so I think you should try something like this:
this.scrollListener = window.addEventListener("scroll", this.handleScroll)
...
handleScroll = (e) => {
...
if(noMoreScroll) window.removeEventListener("scroll", this.handleScroll)
...
}
I hope this helps you :)
Consider revising the way your add the scroll event handler, by passing the handleScroll function directly:
componentDidMount() {
this._isMounted = true;
this.props.onFetchTeams();
/*
With the this.handleScroll bound to this class instance, we can now pass the method
directly to addEventListener as shown
*/
this.scrollListener = window.addEventListener("scroll", this.handleScroll);
}
handleScroll = () => {
const hasMoreLink = this.props.teams["#odata.nextLink"];
if (hasMoreLink == "") {
console.log("remove event handler");
/* This will now work as expected */
window.removeEventListener("scroll", this.handleScroll);
}
/* Rest of your code remains unchanged .. */
}

How to remove scroll event listener?

I am trying to remove scroll event listener when I scroll to some element. What I am trying to do is call a click event when some elements are in a viewport. The problem is that the click event keeps calling all the time or after first call not at all. (Sorry - difficult to explain) and I would like to remove the scroll event to stop calling the click function.
My code:
window.addEventListener('scroll', () => {
window.onscroll = slideMenu;
// offsetTop - the distance of the current element relative to the top;
if (window.scrollY > elementTarget.offsetTop) {
const scrolledPx = (window.scrollY - elementTarget.offsetTop);
// going forward one step
if (scrolledPx < viewportHeight) {
// console.log('section one');
const link = document.getElementById('2');
if (link.stopclik === undefined) {
link.click();
link.stopclik = true;
}
}
// SECOND STEP
if (viewportHeight < scrolledPx && (viewportHeight * 2) > scrolledPx) {
console.log('section two');
// Initial state
let scrollPos = 0;
window.addEventListener('scroll', () => {
if ((document.body.getBoundingClientRect()).top > scrollPos) { // UP
const link1 = document.getElementById('1');
link1.stopclik = undefined;
if (link1.stopclik === undefined) {
link1.click();
link1.stopclik = true;
}
} else {
console.log('down');
}
// saves the new position for iteration.
scrollPos = (document.body.getBoundingClientRect()).top;
});
}
if ((viewportHeight * 2) < scrolledPx && (viewportHeight * 3) > scrolledPx) {
console.log('section three');
}
const moveInPercent = scrolledPx / base;
const move = -1 * (moveInPercent);
innerWrapper.style.transform = `translate(${move}%)`;
}
});
You can only remove event listeners on external functions. You cannot remove event listeners on anonymous functions, like you have used.
Replace this code
window.addEventListener('scroll', () => { ... };
and do this instead
window.addEventListener('scroll', someFunction);
Then move your function logic into the function
function someFunction() {
// add logic here
}
You can then remove the click listener when some condition is met i.e. when the element is in the viewport
window.removeEventListener('scroll', someFunction);
Instead of listening to scroll event you should try using Intersection Observer (IO) Listening to scroll event and calculating the position of elements on each scroll can be bad for performance. With IO you can use a callback function whenever two elements on the page are intersecting with each other or intersecting with the viewport.
To use IO you first have to specify the options for IO. Since you want to check if your element is in view, leave the root element out.
let options = {
rootMargin: '0px',
threshold: 1.0
}
let observer = new IntersectionObserver(callback, options);
Then you specify which elements you want to watch:
let target = slideMenu; //document.querySelector('#oneElement') or document.querySelectorAll('.multiple-elements')
observer.observe(target); // if you have multiple elements, loop through them to add observer
Lastly you have to define what should happen once the element is in the viewport:
let callback = (entries, observer) => {
entries.forEach(entry => {
// Each entry describes an intersection change for one observed
// target element:
});
};
You can also unobserve an element if you don't need the observer anymore.
Check this polyfill from w3c to support older browsers.
Here is my scenario/code, call removeEventListener as return() in the useEffect hook.
const detectPageScroll = () => {
if (window.pageYOffset > YOFFSET && showDrawer) {
// do something
}
};
React.useEffect(() => {
if (showDrawer) {
window.addEventListener("scroll", detectPageScroll);
}
return () => {
window.removeEventListener("scroll", detectPageScroll);
};
}, [showDrawer]);

Categories

Resources