简体   繁体   English

使用JavaScript过滤客户端项目,隐藏或从DOM中删除的最佳实践?

[英]Best practice for filtering items client-side with JavaScript, hide or remove from DOM?

I have a relatively large dataset of items (a few thousand items) that I want to navigate by applying a number of filters client side in a web application. 我有一个相对较大的项目数据集(几千个项目),我想通过在Web应用程序中应用多个过滤器客户端来导航。 Applying the filtering logic itself is not an issue, the question is about which method to use for updating the table of matching results to get the best user experience. 应用过滤逻辑本身不是问题,问题是使用哪种方法来更新匹配结果表以获得最佳用户体验。 The methods I've come up with are: 我提出的方法是:

  1. Setting the class of each row to hide or show it (using visibility: collapsed to hide it), and keeping the DOM element in the table. 设置每行的类以隐藏或显示它(使用可见性:折叠以隐藏它),并将DOM元素保留在表中。
  2. Keeping a DOM element for each data item, detaching/attaching it to the table to hide and show it. 为每个数据项保留DOM元素,将其分离/附加到表以隐藏和显示它。
  3. Just keep an abstract object for each data item, creating a DOM object on demand to show it. 只需为每个数据项保留一个抽象对象,根据需要创建一个DOM对象来显示它。

Which one is likely to give the best user experience? 哪一个可能会提供最佳用户体验? Any other recommended method besides those I've listed already? 除了我已经列出的那些之外的任何其他推荐方法?

If the display area has fixed size (or at least a maximum size), and you must filter on the client-side, I would not create a DOM node for each item, but instead reuse a predefined set of DOM nodes as templates , hiding unnecessary templates depending on the number of results from the filter. 如果显示区域具有固定大小(或至少是最大大小),并且您必须在客户端进行过滤,我不会为每个项目创建DOM节点,而是重用一组预定义的DOM节点作为模板 ,隐藏不必要的模板取决于过滤器的结果数量。 This will drastically reduce the DOM nodes in the document which will keep your page rendering responsive and is fairly easy to implement. 这将大大减少文档中的DOM节点,这将使页面呈现响应并且相当容易实现。

Example HTML*: 示例HTML *:

<ul id="massive-dataset-list-display">
    <li>
       <div class="field-1"></div>
       <div class="field-2"></div>
       <div class="field-n"></div>
    </li>
    <li>
       <div class="field-1"></div>
       <div class="field-2"></div>
       <div class="field-n"></div>
    </li>
    <li>
       <div class="field-1"></div>
       <div class="field-2"></div>
       <div class="field-n"></div>
    </li>
    .
    .
    .
</ul>

Example JavaScript*: 示例JavaScript *:

var MassiveDataset = function(src) {
    var data          = this.fetchDataFromSource(src);
    var templateNodes = $("#massive-dataset-list-display li");

    // It seems that you already have this handled, but just for 
    // completeness' sake
    this.filterBy(someParam) {
        var filteredData = [];
        // magic filtering of `data` 
        this.displayResults(filteredData);
    };

    this.displayResults(filteredData) {
        var resultCount = filteredData.length;

        templateNodes.each(function(index, node) {
            // There are more results than display node templates, start hiding
            if ( index >= resultCount ) {
                $(node).hide();
                return;
            }

            $(node).show();
            this.formatDisplayResultNode(node, filteredData[i]);
        });
    };

    this.formatDisplayResultNode = function(node, rowData) {
        // For great justice
    };
};

var md = new MassiveDataset("some/data/source");
md.filterBy("i can haz filter?");

* Not tested. *未经测试。 Don't expect copy/paste to work, but that would be cool. 不要指望复制/粘贴工作,但那会很酷。

Adding a class and using CSS to show/hide the element will probably be the fastest (coding and performance wise), especially with so much items. 添加一个类并使用CSS来显示/隐藏元素可能是最快的(编码和性能方面),特别是有这么多项目。

If you want to go the DOM manipulation route, consider editing the DOM off-line. 如果您想要进行DOM操作路由,请考虑离线编辑DOM。 Cache the DOM tree in memory (a local variable), update all rows and replace the original DOM node. 在内存中缓存DOM树(局部变量),更新所有行并替换原始DOM节点。 See http://www.peachpit.com/articles/article.aspx?p=31567&seqNum=5 for more information on this matter. 有关此问题的更多信息,请参见http://www.peachpit.com/articles/article.aspx?p=31567&seqNum=5


I've done a project that required filtering items on the location within a Google Maps 'viewport' and a min-max value slider (for those that are curious, it was for a real estate website). 我做了一个项目,需要在Google地图“视口”中的位置过滤项目和最小 - 最大值滑块(对于那些好奇的,它是针对房地产网站的)。

The first version used an AJAX request to get all (server-side) filtered items, so every change in the filter requested new data. 第一个版本使用AJAX请求获取所有(服务器端)过滤项,因此过滤器中的每个更改都请求新数据。 Then the JSON data was parsed to DOM nodes and added to the document. 然后将JSON数据解析为DOM节点并添加到文档中。 Also, in this case search-engine indexing of the items was not possible. 此外,在这种情况下,项目的搜索引擎索引是不可能的。

The second version also used an AJAX request, but this time only requested the filtered ids of the items. 第二个版本也使用了AJAX请求,但这次只请求过滤的项目ID。 All items were present in the HTML with the unique ids and filtered items had an extra class name to initially hide them. 所有项目都存在于HTML中,并带有唯一ID,过滤后的项目有一个额外的类名称,可以最初隐藏它们。 Whenever the filter changed, only the filtered ids were requested and the item's class name accordingly updated. 每当过滤器更改时,仅请求过滤的ID,并相应地更新项目的类名称。 This significantly improved the speed, especially in Internet Explorer (which has the slowest JavaScript engine -of our supported browsers-!)... 这显着提高了速度,特别是在Internet Explorer(我们支持的浏览器中使用最慢的JavaScript引擎 - )中......

I realize that it's not exactly what you're asking for, but since you opened the door for alternates... 我意识到这并不是你所要求的,但是因为你打开了替代品的大门......

Have you considered doing any filtering server-side? 你有没有考虑过任何过滤服务器端? You could load in your results with AJAX if the user changes filtering options, and that way you're not loading thousands of rows of data into a browser when you might only display a portion of them. 如果用户更改过滤选项,您可以使用AJAX加载结果,这样,当您可能只显示其中的一部分时,您不会将数千行数据加载到浏览器中。 It will potentially save you and the visitor bandwith, though this will depend on how your site really gets used. 它可能会保存您和访问者带宽,但这取决于您的网站如何被真正使用。

Basically, if you decide ahead of time what data you want to show, you don't have to go through the trouble of picking over what's there. 基本上,如果您提前决定要显示哪些数据,则不必经历挑选那些数据的麻烦。

I understand that this may not fit your needs, but I offer it as a suggestion in case you were stuck on the idea of client-side. 我知道这可能不符合您的需求,但如果您坚持客户端的想法,我会提供它作为建议。

DOM manipulation is just too slow for "a few thousand items". DOM操作对于“几千个项目”来说太慢了。 Assuming you have a really, really good reason why you aren't getting the server to do the filtering then the best solution I've found is to use client-side XSL transforms on data held as XML. 假设你有一个非常非常好的理由为什么你没有让服务器进行过滤,那么我发现的最佳解决方案是对XML保存的数据使用客户端XSL转换。

Transforms themselves are very quick even on reasonably large data sets. 即使在相当大的数据集上,变换本身也非常快。 You would then ultimately assign the results to the innerHTML property of a containing DIV where you want the table to appear. 然后,您最终将结果分配给包含DIV的innerHTML属性,您希望表格显示在该属性中。 Using innerHTML for large changes in the DOM is way quicker than manipulating the DOM with Javascript. 使用innerHTML进行DOM中的大型更改比使用Javascript操作DOM更快。

Edit : Answers to Justin Johnson's comments:- 编辑 :贾斯汀约翰逊的评论答案: -

If the dataset is that large, the XML is potentially going to be beastly large. 如果数据集很大,那么XML可能会变得非常庞大。

Note I already make the disclaimer in my first paragraph regarding the enlisting of the servers help here. 注意我已经在我的第一段中提出了关于在此处获取服务器帮助的免责声明。 There may be a case here to switch the design around and make sensible use of AJAX, or simply not attempting to show much data at once. 这里可能有一种情况是切换设计并合理使用AJAX,或者根本不尝试一次显示大量数据。 However I'm doing my best to answer the question posed. 但是我正在尽力回答提出的问题。

Its also worth considering that "beastly large" is at least function of bandwidth. 值得考虑的是,“野兽大”至少是带宽的函数。 In a well connected intranet web application bandwidth is not at such a premium. 在连接良好的Intranet Web应用程序中,带宽并不是很高。 In addition I've seen and used implementations that build up and re-use cached XML over time. 此外,我已经看到并使用了随着时间的推移构建和重用缓存XML的实现。

Also, if XML is converted to a DOM object, how is this any better? 此外,如果将XML转换为DOM对象,这又如何更好?

There is massive difference between the technique I propose and direct DOM manipulation by Javascript. 我建议的技术与Javascript直接进行DOM操作之间存在巨大差异。 Consider when code in javascript modifies the DOM the underlying engine has no way to know that other changes are about to immediately follow, nor can it be sure that the javascript will not immediately examine other properties of the DOM. 考虑当javascript中的代码修改DOM时,底层引擎无法知道其他更改将立即跟随,也不能确定javascript不会立即检查DOM的其他属性。 Hence when a change is made to the DOM by Javascript the browser needs to ensure it updates all sorts of other properties so that they are consistent with a completed rendering. 因此,当通过Javascript对DOM进行更改时,浏览器需要确保它更新所有类型的其他属性,以便它们与完成的呈现一致。

However when innerHTML is assigned a large HTML string the browser can quite happily create a whole bunch of DOM objects without doing any recalculations, it can defer a zillion updates to various property values until after the entire DOM as been constructed. 然而,当innerHTML被分配了一个大的HTML字符串时,浏览器可以很愉快地创建一大堆DOM对象而不进行任何重新计算,它可以推迟对各种属性值的大量更新,直到构建完整个DOM之后。 Hence for large scale changes innerHTML will blow direct DOM manipulation out of the water. 因此,对于大规模的改变,innerHTML将直接将DOM操纵从水中吹走。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM