Using VueJS to apply filters to an object causes a decrease in my application's performance

Recently, I've been working on implementing a filter for a search bar.

However, I've noticed that whenever I input something into the search bar, there is a noticeable delay as it loads the entries. I'm not sure if this issue is related to rendering problems or if my approach is simply not suitable given the size of the object, which contains around 2500 entries.

The object structure includes keys such as:

{
  key1: {
    title: 'title',
    description: 'description',
    footerContent: 'footerContent'
  },
  key2: {
    title: 'title',
    description: 'description',
    footerContent: 'footerContent'
  },
  key3: {
    title: 'title',
    description: 'description',
    footerContent: 'footerContent'
  }
}

To filter this object, I have created the following computed function:

filteredItems() {
  if(this.searchQuery) {
    return Object.fromEntries(
      Object.entries(this.items).filter(([key]) => {
        return this.searchQuery
        .toLocaleLowerCase()
        .split(" ")
        .every(
          (word) =>
          key.toLocaleLowerCase().includes(word)
        )
      })
    )
  }
  return this.items
}

Subsequently, in the template, I use a v-for loop like so:

<tbody>
  <tr v-for="item, key in filteredItems" :key="key">
    <td class="align-middle">{{key}}</td>
    <td><input type="text" class="form-control" v-model="item.title"/></td>
    <td><input type="text" class="form-control" v-model="item.description"/></td>
    <td><input type="text" class="form-control" v-model="item.footerContent"/></td>
  </tr>
</tbody>

Answer №1

Expensive costs in web design are not only associated with filtering, but also with rendering. Developing "autocomplete" or "typeahead" functionalities has stemmed from challenges like re-rendering a large HTML table with 2.5k rows on every keystroke - a task that would be equally slow in React, Angular, Svelte, or vanilla JS.

Rendering such a high number of rows translates to managing 12.5k DOM nodes due to the nature of HTML tables where each cell impacts its row and column dimensions. Table rendering is notoriously resource-intensive among DOM layout operations.
Interestingly, companies like Google and Microsoft opted for <div>s with display:flex over traditional Excel grid implementations in their online versions.

In optimizing performance, one efficient solution involves implementing pagination to restrict the number of rendered rows at a time based on viewport capacity. This approach enhances filtering responsiveness without excessive effort.

Pagination should primarily serve as a visual enhancement, keeping all items active in memory while displaying only a limited subset determined by a defined pageSize.


Alternatively, if pagination proves insufficient for presenting your data efficiently, employing a virtual scroller technique could serve as a viable solution. Virtual scrolling typically requires custom calculations using lower-level DOM APIs but can be facilitated through suitable packages.

The concept of a virtual scroller entails creating an empty container to generate scrollbars (referred to as SC) alongside a display window (DW) rendering currently visible content. Subsequent updates to DW contents are synced with SC scroll actions.

For uniform row heights and widths across columns, calculating DW contents is straightforward. Check out this demo simulating 10 billion cells (100k × 100k).

Although complex layouts with variable row heights or flexible column widths necessitate complete rendering initially to lock down respective dimensions, subsequently storing these values allows dynamic positioning of DW contents at different scroll positions.

To implement a virtual scroller with custom cell sizes, follow these steps:

  • Create a parsing container at table mount solely for dimension calculation purposes
  • Store calculated row heights, top positions, and column widths before discarding parsing container
  • Continue with standard virtual scroller set-up, adjusting calculations for specific row display logic
  • Update calculation method upon resize events or data changes
  • Maintain current first visible row in DW for smooth resizing transitions
  • Establish criteria for when stored position data should be refreshed

Educating yourself on the mechanics underlying performance issues equips you to make informed decisions tailored to your use case. Should you choose to tackle the challenge of implementing a virtual scroller and encounter difficulties, I'm available for assistance post your initial attempt. Create a prototype on platforms like codesandbox.io to gauge progress and identify potential roadblocks.

Answer №2

To enhance the performance of your search functionality, there are a few optimizations that can be implemented. While these may not completely resolve your issue, they will certainly provide some benefit.

Firstly, it is advisable not to trigger the search operation with every keystroke. Utilize debounce to introduce a delay in the search action. You can import this feature from Lodash.

The second optimization involves avoiding repetitive calls to

searchQuery.toLocaleLowerCase().split()
as it will produce the same outcome regardless of the object being processed.

import debounce from "lodash/debounce"

filteredItems: debounce(function () {
  if(!this.searchQuery) {
    return this.items
  }

  const searchQueryAsArray = this.searchQuery
    .toLocaleLowerCase()
    .split(" ")

  return Object.fromEntries(
    Object.entries(this.items)
      .filter(([key]) => {
        return searchQueryAsArray.every((word) => key.toLocaleLowerCase().includes(word))
    })
  )
}

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

Unable to bind click eventListener to dynamic HTML in Angular 12 module

I am facing an issue with click binding on dynamic HTML. I attempted using the setTimeout function, but the click event is not binding to the button. Additionally, I tried using template reference on the button and obtaining the value with @ViewChildren, h ...

Is there a way to retrieve the properties of another function within the same component?

I am trying to place NumberFormat inside OutlinedInput and I also need different properties for the format of NumberFormat. (There will be a select window that defines which format property to use). This is what I have: import OutlinedInput from "@ma ...

Error in Heroku deployment - Express and React app displaying a white screen

I am encountering a challenging situation as I attempt to understand the issue at hand. Following the deployment of my React/Express application on Heroku, the build and deployment proceed without errors, but the React frontend appears blank. The browser ...

Send a file using ajax with the help of JavaScript and PHP

Currently, I am looking to implement a method for uploading files using Ajax and JavaScript/PHP without having the page refresh. My initial thought is to use Ajax to send the file using xmlhttp.send(file) and then retrieve it in the PHP script, but I' ...

Error: The module 'https://www.gstatic.com/firebasejs/9.6.0/firebase-app.js' is missing the required export 'default'

I'm currently in the process of setting up and testing Google authentication for a web application that I'm developing. Unfortunately, I've encountered several issues with getting the JavaScript functions to work properly, and I am uncertain ...

Dynamic Search Feature Using AJAX on Key Press

Currently, I have developed an AJAX search function that retrieves keyword values upon key up and triggers the script. The objective is to update the content area with results in alphabetical order as the user types each key. However, the issue I am facin ...

Is it possible to merge node modules that have similar functionalities?

When utilizing node.js, you may encounter module dependencies containing functions with similar functionalities, such as underscore, lodash, and lazy (potentially in different versions). Is there a way to specify which module from a group of similar metho ...

error when trying to bind attributes to knockout components

I am trying to dynamically add an id attribute to a tag, but it keeps giving me an error. "Uncaught ReferenceError: Unable to process binding "attr: function (){return {id:id} }" Message: id is not defined" Here is my HTML code- <label data-bind= ...

Refresh the component following a successful POST request in Vue.js

Having issues with reloading components in my VueJS app using NUXTJS. The page in my app calls a component called “CustomerCard.” When I use fetch to communicate with my API and retrieve all customers, everything works perfectly upon arriving on the p ...

Escaping an equal sign in JavaScript when using PHP

I am currently working on the following code snippet: print "<TR><TD>".$data->pass_name."</TD><TD><span id='credit'>".$data->credit_left."</span></TD><TD><input type='button' val ...

Navigate a user upon completion of an update

My webpage requires users to click an update link, which triggers a process of fetching data from an API that takes a few minutes. I don't want users to have to constantly refresh the page to know when the process is complete and they can continue. Is ...

Applying CSS to an iframe using JavaScript: A Step-by-Step

I have an Iframe editor and I am trying to change some CSS inside the editor. However, when I attempt to apply the CSS, it does not affect the styles within the Iframe. <div id="editor" style="flex: 1 1 0%;"> <iframe src="https://editor.unlay ...

how to forward visitors from one URL to another in a Next.js application

I have an existing application that was initially deployed on , but now I want to change the domain to https://example.com. What is the best way to set up redirection for this domain change? I have attempted the following methods: async redirects() { r ...

How can one properly extend the Object class in JavaScript?

I have a scenario where I want to enhance a record (plain Javascript object) of arrays with additional properties/methods, ideally by instantiating a new class: class Dataframe extends Object { _nrow: number; _ncol: number; _identity: number[]; co ...

The useMutation function trapped in an endless loop

I've been encountering an issue while running a query to save an entity in the database using usemutation. The saveVisa() mutation seems to be stuck in an infinite loop, creating the same element multiple times without any clear reason. import {React, ...

Developing a password strength checker using Javascript for ultimate security

Currently encountering an issue with my javascript project. The main goal is to validate user input against a list of known bad passwords and also their "1337" versions. Initially, checking for the basic bad password list was straightforward. However, th ...

Unable to load JSON information into an ExtJS grid

I have exhausted all the solutions I found (there are many on Stackoverflow) in an attempt to fix my extjs store issue. Despite ensuring that the grid is displayed correctly, the data still refuses to show up. Feeling perplexed, I am sharing the "store" co ...

Interacting with a Web API using JavaScript following successful authentication with Azure AD B2C

Currently, I am working on a .Net Web App. After going through the authentication process with Azure AD B2C using the Azure AD Connect protocol, my app's controller successfully obtains an access token via the MSAL library (written in C# code) to conn ...

Attempting to dynamically link my "ng-true-value" in AngularJS

Working with values retrieved from a database, my goal is to include a checkbox, load the description, and provide 2 text boxes – one editable and the other read-only. Both text boxes initially display values from the database. When the checkbox is chec ...

What design pattern serves as the foundation for Angularjs? Is mastering just one design pattern sufficient?

Although I have been teaching myself Angular and can understand how to code in it, I realize that simply learning the concepts of AngularJS and coding or tweaking things to solve problems is not enough. Moving forward, my goal is to write effective and sta ...