I am experiencing significant lag when attempting to use the Vue mouseover event to manipulate the styles of two elements. Are there any alternative methods that could achieve the same

I'm fairly new when it comes to using Vue, so I might not be approaching this in the most efficient manner. My challenge involves a table of rows generated via a v-for loop, accompanied by a list of corresponding row titles also created through a v-for loop. These need to be treated as separate DOM elements in order to facilitate fixed header scrolling. The goal is to change the color of both the row and its title when hovering over a specific row.

In an attempt to achieve this with Vue, my thought process followed these steps:

  1. When hovering over an element, set a data property to store the index of that particular element.
  2. Apply a class binding to the elements in question, allowing their styles to change when the stored index matches their respective indices from the v-for loop.

While this approach technically works, the code execution tends to be sluggish and slow. Despite having a moderate number of rows (40) and columns (60), it doesn't seem like an excessive amount.

A summarized version of the code can be seen below:

Template html

<div class="rowTitle" 
  v-for="(rowName, i) in yAxis.values" :key="i"  
  @mouseover="hover(i)" 
  :class="hoverActive(i)" >{{rowName}}</div>

<div class="row" 
  v-for="(row, i) in rows" :key="i"
  @mouseover="hover(i)"
  :class="hoverActive(i)" >{{row}}</div>

Vue object

export default {
  data:()=>(
    {
      rows: rows,
      yAxis: yAxis,
      rowHover: -1,
    }
  ),

  methods:{
    hover(i) {
      this.rowHover = i
    },
    hoverActive(i) {
      return this.rowHover == i ? 'hover' : ''
    }
  },
}

Answer №1

One possible explanation is that the hover event is triggering very frequently, causing Vue to re-render each time. Adding a debounce to the event handler or marking it as passive could significantly improve performance. In the code snippet below, I demonstrate using a passive event modifier in Vue to instruct the browser not to prioritize this particular event handler over essential processes like rendering (refer to https://v2.vuejs.org/v2/guide/events.html#Event-Modifiers).

If feasible, solving the issue with CSS, as suggested by a commenter (see https://developer.mozilla.org/en-US/docs/Web/CSS/:hover), is highly recommended since browsers tend to perform well with this approach. However, there are situations where CSS alone may not suffice, in which case implementing a debounce or a passive event listener could be a viable alternative. Additionally, you could explore the "stop" modifier (stop propagation) for further optimization if necessary.

const tableData = [];
for (let i = 0; i < 40; i++) {
  tableData.push([]);
  for (let j = 0; j < 60; j++) {
    tableData[i].push({
      i,
      j
    });
  }
}

Vue.component('customTable', {
  props: ['tableData'],
  data() {
    return {
      currentRow: -1
    }
  },
  template: `
    <div class="table">
      <div class="row" v-for="(row, x) in tableData">
        <span v-for="cell in row"
              @mouseover.passive="handleMouseOver(x)"
              :class="checkActiveRow(x)"
              class="row-cell" 
              >i:{{cell.i}},j:{{cell.j}}</span>
      </div>
    </div>
  `,
  methods: {
    handleMouseOver(i) {
      this.currentRow = i
    },
    checkActiveRow(i) {
      return this.currentRow == i ? 'hover' : ''
    }
  }
})

var vueApp = new Vue({
  el: '#app',
  data() {
    return {
      tableData
    }
  }
})
body {
  font-size: 11px;
}

.row-cell {
  min-width: 40px;
  display: inline-block;
  border: 1px solid gray;
}

.row-cell.hover {
  color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  My custom table
  <custom-table :tableData="tableData" />
</div>

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

Issue with offset calculation in bootstrap table occurs when the bootstrap-table is closed and the window is resized

In a recent project, I utilized the bootstrap table. However, upon closing the bootstrap table with the following script: $(document).ready(function () { $(".removetable").click(function (e) { $(".table-aria").remove(); ...

The notification panel pop-up box keeps moving away from the right side

I'm currently in the process of creating a straightforward vertical notification panel, similar to the one seen on Stack Overflow. However, I've encountered an issue where the pop-up is not staying positioned correctly to the right side. It behav ...

Send information from a web page's elements to PHP with the help of AJAX

My goal is to integrate AJAX, HTML, and PHP to create a seamless user experience. I am currently facing difficulty in passing variables to the PHP form. The method I've employed seems a bit complex, especially since this is my first attempt at using A ...

Automatically closing HTML tags using Vanilla JavaScript

When a user inputs a tag, such as <div>, JavaScript is supposed to close it with </div>. However, this should not happen for non-HTML tags like <hello>. I attempted to achieve this using the method str.repeat, but the results were not as ...

Guide on installing React packages during runtime

My React project has a number of packages that need to be installed, but they take up a lot of disk space. I would like to install them only when necessary, after the user interacts with a specific component that requires these packages. Is there a way t ...

Chrome is struggling to load pages, forcing users to scroll endlessly to find the content they are looking for

Encountering a problem where Chrome occasionally displays a particular page off-screen. Currently using Mac OSX, working on a Backbone.js App with client-side development only, no PHP/Node. The page is loading completely off-screen, requiring me to scrol ...

Stylus mistakenly fetches styl files from an incorrect directory

My issue involves a file named mobile.styl, which gathers all necessary styl files using the @import function: @import '../../common/styles/colors' @import '../../common/styles/init' @import 'landing' @import 'faq&apos ...

How can I automatically redirect a React page once I receive a response from Express?

I'm facing an issue with redirecting from one page to another in React. The setup involves an Express server serving the required data to React, and upon receiving the data in React, the goal is to display that result on another page by triggering a r ...

Use jQuery to parse the JSON below and then showcase the information in an HTML table

Can anyone assist me with parsing the following JSON using jQuery and presenting it in an HTML table? I want to showcase the values of "key" and "doc_count" in an HTML table. Your help would be greatly appreciated. Please find the JSON data below: { ...

Mistakenly appearing at the top of the window instead of the bottom of the window

Utilizing Vue.js to fetch resources from a Laravel API periodically and paginate(), after retrieving the initial 10 instances, I aim to get the next 10. Here's how my method looks: scroll () { window.onscroll = () => { let bottomOf ...

Managing single sign-out with SSO using the Msal v2 library in a Node.js and Vue.js environment

The challenge: When using msal v2, logging in to the app via a Microsoft account saves parameters to the sessionStorage. Everything works perfectly until the user logs out on Office.com or any other site using Microsoft SSO. The problem arises because the ...

What is causing the added assets to not be saved in the hyperledger registry?

I have the application code below in my Hyperledger composer environment (My question pertains only to the RequestT transaction as I have not yet written the Respond transaction code): Data Model Code (.cto) /* * Defines a data model for chama transactio ...

Is it recommended for Protractor Page Objects to reveal ElementFinder?

Our team is currently debating whether or not to prohibit the exposure of "ElementFinder" and "ElementArrayFinder" in our Page Objects. The main point of contention is a quote by Simon Stewart. Page Objects Done Right - selenium conference 2014 (page.7) ...

LocalStorage is designed to hold only the most recent data input

As I work on developing an app using PhoneGap for iOS, I encounter an issue with LocalStorage. After entering and storing a username and password on my iPad, I close the app, open it again, and enter a new set of login credentials. However, when inspecting ...

Take a snapshot of the landing page to analyze its content

At the school district where I work, we have a unique system in place that allows parents to access district and class resources. This system involves using a third-party product, which unfortunately has caused some issues. When a parent logs in, they are ...

Issue with joining tables in query on Cordova Mobile app

I have 2 queries that will return results which I plan to use in JSON format. The first query is $query = "SELECT * FROM info_location WHERE location_id=".$id.""; and the second query $query = "SELECT t1.location_id,t1.street,t1 ...

The useEffect hook in Next.js does not trigger a re-render when the route changes

I'm currently experiencing an issue with a useEffect inside a component that is present in every component. I've implemented some authentication and redirection logic in this component, but I've noticed that when using Next.js links or the b ...

Is there a dependable API available for capturing window screenshots using either JavaScript or PHP?

Would it be possible to capture a screenshot of window or div elements using JavaScript? I tried using "HTML5's CANVAS" but the quality of the result was not satisfactory. Is there a more reliable API available for this task? ...

odd appearance when objects make contact with one another

I am encountering a peculiar issue with my threejs objects in a scene. Whenever they get near each other or touch, I notice strange triangular artifacts forming at the borders of the objects, as shown in the image below. The renderer being used is THREE.W ...

Dynamic way to fetch computed properties in VueJS

I am trying to find a way to calculate the sum of computed properties that begin with the string calculateSum. The challenge is that I cannot access their names using this.computed. Here is my approach: getSubTotal(){ var computed_names = []; var ...