Tips for sending a changing mouse scroll value as a property in VueJS

I am currently utilizing the Laravel - VueJS framework.

My goal is to detect the Y position of the mouse scroll and pass it dynamically as a prop to a Navbar component. To achieve this, I set up an eventListener and stored the window.scrollY value in a variable called scrollPos within the data(). Then, I passed scrollPos as a prop to the Navbar component using v-bind:scrollPos="scrollPos". However, the value being passed to the Navbar component remains at 0 and does not update with further mouse scrolling.

<Navbar v-on:scroll="this.changeScrollPos" v-bind:scrollPos="scrollPos" />

mounted() {

        console.log('Component mounted.');
        window.addEventListener('scroll', function(e) {
                this.scrollPos = window.scrollY;
                console.log(this.scrollPos);
        });

},
data() {
    return {
        scrollPos: 0
    }
}, 
methods: {
    changeScrollPos() {
        console.log('Mouse scrolled');
    }
}

In the Navbar component, I simply want to display this value in the navigation bar, which is fixed at the top of the page and contains router-links that scroll to specific sections when clicked.

<nav class="nav" id="nav">
    <div class="nav-content>
        <ul class="nav-items">
            <li class="nav-item"><router-link to="/" v-scroll-to="'#section1'">{{ scrollPos }}</router-link></li>
        </ul>
    </div>
</nav>

<script>
    export default {
        props: [
            "scrollPos"
        ]
    }
</script>

I also attempted to use the

v-on:scroll="this.changeScrollPos()"
method to check if this method is triggered after any mouse scroll changes, but it did not work.

If anyone can offer insights into why this setup is not functioning as expected and help me in passing dynamic mouse scroll values to the Navbar component, it would be greatly appreciated.

Edit: While similar to Watch window.scrollY changes in Vuejs, the issue discussed there has been resolved. In my case, the challenge lies in passing the real-time changing mouse scroll value to the component so that the Navbar reflects these updates dynamically.

Answer №1

The issue you are facing is not specific to Vue, but rather a common JavaScript problem related to the this function context.

In a regular function, the value of this can vary depending on how the function was called (Check out this page for more information). In your scenario, the this inside the callback function passed to the addEventListener function will be undefined because it is not bound to anything specific.

mounted() {
  window.addEventListener('scroll', function(e) {
    this.scrollPos = window.scrollY; // this is undefined here 
  });
}

If you want to make this refer to the Vue instance within a regular function, you can manipulate variable scope like this:

mounted() {
  const THIS = this; 
  window.addEventListener('scroll', function(e) {
    THIS.scrollPos = window.scrollY; // THIS refers to the Vue instance here
  });
}

Prior to ES6, this was the commonly used method to achieve this. With ES6 and the introduction of arrow functions, it became much simpler since arrow functions do not bind the this variable:

mounted() {
  window.addEventListener('scroll', e => this.scrollPos = window.scrollY);
}

This approach offers cleaner syntax, which is why it is now preferred. Just keep in mind that arrow functions are not supported in IE11 and below, so you may need to use a pre-compiler like Babel (which you are likely already using).

Answer №2

After taking advice from Slim, I made the decision to refactor my function into an arrow function and surprisingly, it now functions properly. Despite this success, I am still unclear on the reasons behind why this adjustment resolved the issue. It would greatly benefit me if someone could provide a clear explanation.

mounted() {
    window.addEventListener('scroll, () => { this.scrollPos = window.scrollY; });
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The modules exporting lack the necessary context for this

I'm not entirely happy with how the question is phrased. Feel free to suggest any improvements. Also, please understand that my frustration might be due to a mix of ignorance and annoyance which could result in inaccurate assessments of the issue. I a ...

Guide on converting JSON to CSV in React by utilizing the map function

When I convert JSON data to CSV by clicking a button, it currently stores the data in the CSV file separated by commas. However, I want each piece of data to be on its own line. How can I achieve this? For example: Minor,Minor What I Want: Each item on a ...

Display or conceal a frame with the help of JavaScript or jQuery

Is there a simple way to hide the "topFrame" and "menu" frames when clicking an image or button, and then unhide them by clicking again? Apologies for not including the "topFrame" and "menu" jsp files, as they are dynamically generated in my application. ...

Struggling with an issue in React and Bootstrap4 while developing an application with create-react-app

In my experience with Windows 10, I encountered two scenarios where I faced problems. The first scenario involved creating applications using the create-react-app command and installing it with npm i -g [email protected]. Scenario 1 I stopped the React s ...

The CORS policy is preventing access: The requested resource does not have the necessary 'Access-Control-Allow-Origin' header. Transitioning from Vue to Spring

Having trouble with axios in Vue connecting to Spring Check the vue component script View an image related to this issue here Also review your vue.config.js file Make sure your Spring controller is set up correctly If you're getting an error code ...

Deselect a checkbox by selecting a radio button with just Javascript code

Hey there! I'm currently delving into the world of pure JavaScript and could really use some guidance on a particular issue. Here's what I'm aiming to accomplish: I'd like to design a checkbox that triggers the opening of a window whe ...

The AngularJS application appears to have trouble accessing a local text file, even when it is deployed on

Within the same directory of my application deployed on IIS, there are 4 files: home.html Angular.js data.txt web.config (Automatically generated by IIS for default document) I am looking to display the content of 'data.txt' on 'home.html ...

skip every nth element in the array based on the specified value

The Challenge I'm currently working on a graph that relies on an array of data points to construct itself. One major issue I've encountered is the need for the graph to be resizable, which leads to the necessity of removing certain data points ...

What's the best way to switch between colors in a Vue list?

I have a custom tree-view component that I'm working on: <template> <li class="main__li list" :style="{'margin-left': `${depth * 20}px` ,'background-color': `${col}`}" @click="toggle(e); getEl( ...

What is the best way to combine this PHP, Javascript, and HTML document together?

My goal is to upload a CSV file exclusively using an HTML form and then save it in an array using PHP and Javascript. I have individual codes that work perfectly when used as separate files. However, when I attempt to combine them into one file, the Javas ...

Using SetInterval function in conjunction with jQuery's .each() method

I'm looking to cycle through a group of divs and perform random actions at various intervals. I'm trying to use the function below, but the console.log always returns the same object and integer for each iteration. What would be the correct way t ...

"Enhance the appearance of bootstrap buttons by applying CSS to add shadow and border when the

Working on a frontend project using the React framework and Bootstrap 5.3 for design. Noticing that shadows are deactivated in Bootstrap by default, which means buttons don't display shadows when active as per the Bootstrap v5.0 documentation. Link ...

Error in MongoDB Connection: Timeout issue caused by an unresolved Promise

Issue Overview Whenever I attempt to execute nodemon server, a timeout error is displayed indicating [nodemon] app crashed - waiting for file changes before starting.... Detailed Problem Description I have three files located at the following paths: ...

Show the present category name within breadcrumbs (utilizing angularJS)

Struggling to display category and vendor names on breadcrumbs? Utilizing the ng-breadcrumbs module but encountering difficulties in making curCategory and curVendor globally accessible. Tried various methods without success. Below is the HTML code snippe ...

Is it possible to manipulate the response from a MySQL server using Node.js?

For example: The following response represents the original data { "todo_id": 2, "todo_item": "brush your teeth", "scheduled_time": "2020-03-22T07:14:29.000Z", "user_id": 1, "is_done": { "type": "Buffer" ...

What is the best way to incorporate a logo container and a horizontal divider into my top navigation bar using Bootstrap?

I'm currently working on designing a top navigation bar that features a logo with color #1 as the background on the left side. The logo is then separated by a grey horizontal divider, followed by color #2 representing the application name beside the d ...

Looking to update a specific element in an array on an hourly basis?

var temperature = [-18 , -18.1 , -18.2, -18.3, -18.4, -18.5, -18.6, -18.7,-18.8, -18.9, -19 , -19.1 , -19.2, -19.3, -19.4, -19.5, -19.6, -19.7,-19.8, -19.9, -20]; $(".warlotemp").html(temperature[0]); $(".warlotemp").append(" C"); I am intere ...

When using the HTML5 draw img feature, only the top 1/4 of the image will be

I am having trouble loading a full image into canvas. Currently, it only displays the top 1/4 of the image regardless of which one I use. Any help would be greatly appreciated. Here is the code snippet in question: var canvas = document.getElementById(&ap ...

Classic design of the shadow element

I have main.js and index.html below class CustomTagA extends HTMLElement { constructor() { super(); const shadow = this.attachShadow({mode: 'open'}); const wrapper = document.createElement('h1'); ...

The power of MobX lies in its ability to provide a deep

I'm currently delving into the concept of deep observability in MobX. I'm looking for insights on why the autorun function is not being triggered every time I call setCommentCountForPost in the code snippet below. Can someone point me in the rig ...