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

Ways to utilize jquery to limit the length of an editable div and prevent it from exceeding our specified restriction

Imagine a scenario where you have the following code snippet: <div id="editing" contenteditable onclick="document.execCommand('selectAll',false,null)">Put text here...</div> In this situation, let's say you want to impose a r ...

"Unraveling the Mystery of jQuery In

I am facing an issue with integrating jQuery into my code. I have always followed the same method, which has worked in the past, but now it seems to be causing problems for me. I suspect it may be because I am not on my usual laptop, although when I visite ...

A guide on updating a boolean field in the database using ajax

Here is a piece of my html code: <form action="" method="post"> {% csrf_token %} {% if donate.is_taken == False %} <br> <button type="submit" class="btn" name="taken_or_not" ...

Is there a way to incorporate cell highlighting on IE?

I've implemented a method to highlight selected cells based on the suggestion from jointjs. It surrounds the cell with a 2-pixel red border, which works well in Chrome. However, I need the outline to work in IE as well. Unfortunately, when I reviewed ...

The jQuery UI Dialog is experiencing an issue with a button that is triggering a HierarchyRequest

I am facing an issue with a piece of javascript that works perfectly on other pages but is now throwing a HierarchyRequestError on a new page. This leads me to believe that there may be an HTML problem on this particular page. Here is a simplified version ...

React - How to Close Material-UI Drawer from a Nested Menu

Currently, I am utilizing a fantastic example (here) to create a dynamic nested menu for my application. Taking it a step further, I am trying to integrate it into a Material UI appbar/temporary drawer. My goal is to close the drawer when the user clicks o ...

Issues with executing basic unit test in Angular Js

THE ISSUE: In an attempt to create unit tests for my Angular application, I set up a basic test app and wrote a simple unit test. However, the test is not functioning as expected. APPLICATION CODE: var app = angular.module( 'myApp', [] ); app ...

Discovering the most recent Node.js version: A step-by-step guide

Is it possible to check the latest available Nodejs version using npm? While node -v allows us to see the current version, I am curious if there is a way to access the most recent version through JavaScript. For example, process.version can be used to vi ...

Utilize the return value within a .map function following the completion of a request.get call

Essentially, for security reasons, I need to convert an image from a URL to base64. Currently, I have two functions in place. One function is responsible for converting the image from the URL to base64, and the other function is iterating over the databas ...

Angular's implementing Controller as an ES6 Class: "The ***Controller argument is invalid; it should be a function but is undefined."

Struggling to create a simple Angular todo application using ES6. Despite the controller being registered correctly, I keep encountering an error related to the title when navigating to the associated state. *Note: App.js referenced in index is the Babel ...

JQuery integration resulting in disappearance of Input-group-btn element

Allow me to explain my current project. I am in the process of developing a Modal that enables users to input a password There will be an option to toggle between showing or hiding the text in the password field using a button positioned on the right sid ...

"Troubleshooting: Issues with Ajax's .load() function disrupting

I'm encountering a strange issue where the load() function is causing my carousel to malfunction. Within my Slick Slider, I have 3 slides. You can navigate to the next slide by clicking the NEXT button. Alternatively, clicking on the slide itself loa ...

Children divs unable to access Angular scope

This section is from my controller: mbpMod.controller("bookController", function($scope,api) { ... $scope.bookTable=new BookTable(); $scope.bookLabel="Book"; ... } On the HTML page, it functions properly with this code: <md-tab> ...

Learn how to implement a vertical bar chart in Highcharts by using it as a component and passing it as props

I recently imported a Bar Chart component from Highcharts, but it is being displayed horizontally. I would like to convert it into a vertical chart instead. Can someone please assist me in achieving this by passing the necessary props? <template v-slot ...

Having trouble navigating to the bottom of a VUEJS app?

I've been working on developing a chatbot app that utilizes a REST API to stream content. While the functionality of the app is running smoothly, I have encountered an issue with the scroll to bottom feature. Instead of automatically scrolling to disp ...

Steps to display a variable in JavaScript on an HTML textarea

I'm working on a JavaScript variable called 'signature' var signature; //(Data is here) document.write(signature) Within my HTML document, I have the following: <div id="siggen"> <textarea id="content" cols="80" rows="10">& ...

Tips on effectively utilizing dynamic data with Google Charts

I am working on creating a dynamic chart using Google Charts with multiple CSV files. I want to display a different chart depending on the selection made by the user. The first file loads successfully and displays a chart, but the $("#selection").change(.. ...

Issue with AJAX request on Internet Explorer versions 8 and 9

This script is functioning properly in Internet Explorer 10 and above, as well as Chrome and other browsers. However, it encounters issues specifically with IE8 and IE9. <table id="table" border="1"> <tbody style="display: table-row-group"&g ...

What is the process for configuring vue.config.js with typescript?

Just starting out with typescript and running into an issue while configuring vue.config.js const webpack = require("webpack"); module.exports = { plugins: [ new webpack.DefinePlugin({ __VUE_I18N_FULL_INSTALL__: true, __ ...

Angular2 - How to track or listen for (click) events on dynamically inserted HTML elements

I'm trying to inject a string with a dynamically retrieved (click) event into an Angular2 template. Since this string is fetched from the back-end after the DOM is loaded, Angular doesn't recognize the injected event. Here's an example of t ...