Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/413.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用纯Javascript过滤非常大的引导表_Javascript_Twitter Bootstrap_Dom_Infinite Scroll - Fatal编程技术网

如何使用纯Javascript过滤非常大的引导表

如何使用纯Javascript过滤非常大的引导表,javascript,twitter-bootstrap,dom,infinite-scroll,Javascript,Twitter Bootstrap,Dom,Infinite Scroll,我已经在bootstrap中构建了一个大表,大约5000行x 10列,我需要快速过滤表中的特定属性,只使用JavaScript。该表同时具有id列和属性列,即 id | attr | ... --------------- 2 | X | ... 3 | Y | ... 4 | X | ... 为了加快过滤过程,我构建了一个哈希表,将属性映射回列ID。例如,我有一个映射: getRowIds["X"] = [2,4] 用户可以在搜索框中输入属性“X”,然后哈希表查找包

我已经在bootstrap中构建了一个大表,大约5000行x 10列,我需要快速过滤表中的特定属性,只使用JavaScript。该表同时具有id列和属性列,即

id | attr | ...
---------------
2  |  X   | ...
3  |  Y   | ...
4  |  X   | ...
为了加快过滤过程,我构建了一个哈希表,将属性映射回列ID。例如,我有一个映射:

getRowIds["X"] = [2,4]
用户可以在搜索框中输入属性“X”,然后哈希表查找包含“X”的对应行(本例中为2和4),然后通过映射操作调用以下函数:

this.hideRow = function(id) {
    document.getElementById(id).style.display="none"
}

this.showRow = function(id) {
    document.getElementById(id).style.display=""
}
这个过程仍然相当缓慢,因为允许用户选择多个属性(比如X,Y)

有没有更快的方法隐藏行

如果我能以某种方式将表从DOM中分离出来,进行更改,然后重新连接,会更快吗?如何在javascript中实现这一点

还有其他更有效/更智能的过滤方法吗

谢谢:)

我想问一下

  • 为什么要为自己编写此代码?从个人经验来看,尝试在所有浏览器上高效过滤是一项不平凡的任务
  • 若您将此作为一种学习体验,请查看下面列出的软件包的来源作为示例
  • 对于5000行,进行服务器端筛选和排序会更有效。然后使用ajax更新显示的表
我建议您考虑使用已经实现这一点的几个JavaScript包中的一个。下面的两个程序包还有很多。我将展示这两个示例,作为可用的示例

  • -这是一个功能非常全面的软件包,可处理客户端和服务器端的筛选和排序
  • -是一个轻量级客户端筛选和排序包

最好的选择是不要渲染所有这些内容并存储它们的对象版本,而通过分页一次最多只能显示50行。用JS在内存中存储这么多对象没有问题。另一方面,将所有这些存储在DOM中会让浏览器束手无策。5000大约是浏览器在一台好的机器上可以做到的上限,同时保持良好的性能。如果你开始修改其中的一些行并调整一些东西(“隐藏”、“显示”),事情肯定会变得更慢

这些步骤类似于:

  • 将数据组织到一个对象数组中,您的哈希映射非常适合用于补充和快速访问目的
  • 编写一些排序和筛选函数,为您提供所需的数据子集
  • 编写一个分页器,这样您就可以获取数据集,然后根据一些修改的参数获取下一个数据集
  • 将“绘制/渲染”或“更新”方法替换为显示符合输入条件的当前50组的方法
  • 以下代码应视为可能有效的伪代码:

    // Represents each row in our table
    function MyModelKlass(attributes) {
        this.attributes = attributes;
    }
    
    // Represents our table
    function CollectionKlass() {
        this.children = [];
        this.visibleChildren = [];
        this.limit = 50;
    }
    
    CollectionKlass.prototype = {
        // accepts a callback to determine if things are in or out
        filter: function(callback) {
            // filter doesn't work in every browser
            // you can loop manually or user underscorejs
            var filteredObjects = this.children.filter(callback);
    
            this.visibleChildren = filteredObjects;
            this.filteredChildren = filteredObjects;
            this.showPage(0);
        },
        showPage: function(pageNumber) {
            // TODO: account for index out of bounds
            this.visibleChildren = this.filteredChildren.slice(
               pageNumber * this.limit,
               (pageNumber + 1) * this.limit
            );
        },
        // Another example mechanism, comparator is a function
        // sort is standard array sorting in JS
        sort: function(comparator) {
            this.children.sort(comparator);
        }
    }
    
    function render(el, collection, templateContent) {
        // this part is hard due to XSS
        // you need to sanitize all data being written or
        // use a templating language. I'll opt for 
        // handlebars style templating for this example.
        //
        // If you opt for no template then you need to do a few things.
        // Write then read all your text to a detached DOM element to sanitize
        // Create a detached table element and append new elements to it
        // with the sanitized data. Once you're done assembling attach the
        // element into the DOM. By attach I mean 'appendChild'.
        // That turns out to be mostly safe but pretty slow. 
        //
        // I'll leave the decisions up to you.
        var template = Handlebars.compile(templateContent);
        el.innerHTML(template(collection));
    }
    
    // Lets init now, create a collection and some rows
    var myCollection = new CollectionKlass();
    
    myCollection.children.push(new MyModelKlass({ 'a': 1 }));
    myCollection.children.push(new MyModelKlass({ 'a': 2 }));
    
    // filter on something...
    myCollection.filter(function(child) {
        if (child.attributes.a === 1) {
            return false;
        }
    
        return true;
    });
    
    // this will throw an out of bounds error right now
    // myCollection.showPage(2); 
    
    // render myCollection in some element for some template
    render(
        document.getElementById('some-container-for-the-table'), 
        myCollection,
        document.getElementById('my-template').innerHTML()
    );
    
    // In the HTML:
    
    <script type="text/x-handlebars-template" id="my-template">
        <ul>
            {{#each visibleChildren}}
                <li>{{a}}</li>
            {{/each}}
        </ul>
    </script>
    
    //表示表中的每一行
    函数MyModelKlass(属性){
    this.attributes=属性;
    }
    //代表我们的桌子
    函数集合Klass(){
    这是:children=[];
    this.visibleChildren=[];
    这个极限=50;
    }
    CollectionKlass.prototype={
    //接受回调以确定事物是进入还是退出
    过滤器:函数(回调){
    //过滤器在每个浏览器中都不起作用
    //您可以手动循环或使用下划线进行循环
    var filteredObjects=this.children.filter(回调);
    this.visibleChildren=过滤对象;
    this.filteredChildren=filteredObjects;
    此.showPage(0);
    },
    显示页面:功能(页码){
    //TODO:说明索引超出范围
    this.visibleChildren=this.filteredChildren.slice(
    页码*这是一个限制,
    (页码+1)*此限制
    );
    },
    //另一个示例机制,比较器是一个函数
    //排序是JS中的标准数组排序
    排序:函数(比较器){
    this.children.sort(比较器);
    }
    }
    函数呈现(el、集合、模板内容){
    //由于XSS的原因,这部分比较难
    //您需要清理正在写入或删除的所有数据
    //使用模板语言。我会选择
    //此示例中的把手样式模板。
    //
    //如果您选择无模板,那么您需要做一些事情。
    //将所有文本写入然后读取到分离的DOM元素以进行清理
    //创建分离的表元素并向其附加新元素
    //使用经过清理的数据。组装完成后,连接
    //元素添加到DOM中。我指的是“appendChild”。
    //结果证明,这是最安全的,但相当缓慢。
    //
    //我将把决定权留给你。
    var template=handlebar.compile(templateContent);
    el.innerHTML(模板(集合));
    }
    //现在让我们初始化,创建一个集合和一些行
    var myCollection=new CollectionKlass();
    myCollection.children.push(新的MyModelKlass({'a':1}));
    myCollection.children.push(新的MyModelKlass({'a':2}));
    //过滤某些东西。。。
    myCollection.filter(函数(子级){
    if(child.attributes.a==1){
    返回false;
    }
    返回true;
    });
    //这将立即抛出一个越界错误
    //myCollection.showPage(2);
    //在某个模板的某个元素中呈现myCollection
    渲染(
    document.getElementById('some-container-for-the-table'),
    我收集,
    document.getElementById('my-template').innerHTML()
    );
    //在HTML中:
    
      {{#每个可访问的儿童}
    • {{a}
    • {{/每个}}
    请参阅链接,它可能会有所帮助,唯一的问题是它不在纯javascript中,它也使用angularjs

        app.service("NameService", function($http, $filter){
    
      function filterData(data, filter){
        return $filter('filter')(data, filter)
      }
    
      function orderData(data, params){
        return params.sorting() ? $filter('orderBy')(data, params.orderBy()) : filteredData;
      }
    
      function sliceData(data, params){
        return data.slice((params.page() - 1) * params.count(), params.page() * params.count())
      }
    
      function transformData(data,filter,params){
        return sliceData( orderData( filterData(data,filter), params ), params);
      }
    
      var service = {
        cachedData:[],
        getData:function($defer, params, filter){
          if(service.cachedData.length>0){
            console.log("using cached data")
            var filteredData = filterData(service.cachedData,filter);
            var transformedData = sliceData(orderData(filteredData,params),params);
            params.total(filteredData.length)
            $defer.resolve(transformedData);
          }
          else{
            console.log("fetching data")
            $http.get("data.json").success(function(resp)
            {
              angular.copy(resp,service.cachedData)
              params.total(resp.length)
              var filteredData = $filter('filter')(resp, filter);
              var transformedData = transformData(resp,filter,params)
    
              $defer.resolve(transformedData);
            });  
          }
    
        }
      };
      return service;  
    });
    
    使用确实是个好主意, 这使我们可以将您的行渲染为

    <tr ng-repeat="row in rowArray">
      <td>{{row.id}}</td>
      <td>{{row.attr}}</td>
    </tr>
    
    话虽如此,向数组中抛出5K行显然是一个性能阻力。这将在你的眉毛中创建一个巨大的HTML
    <tr ng-repeat="row in rowArray | yourCustomFilter:parameters">
      <td>{{row.id}}</td>
      <td>{{row.attr}}</td>
    </tr>
    
    document.getElementById(id).style.display="none"  
    
    hash[id] = document.getElementById(id).style.display
    
    hash[id] = 'none'
    hash[id] = 'block'
    
    elem[id] = $('<tr>' +
      '<td>' + id + '</td>' +
      '<td>' + attr + '</td>' +
    </tr>');
    
    display[id] = elem[id].style.display;
    
    elementArray = [rowElement1, ..., rowElementN]
    
    var htmlToAppend = elementArray.join('');
    
    parentElement.append(htmlToAppend);
    
    addFilter(yourTable, 2, ['X','Y']);
    
    function SearchRecordsInTable(searchBoxId, tableId) {
        var searchText = document.getElementById(searchBoxId).value;
        searchText = searchText.toLowerCase();
        var targetTable = document.getElementById(tableId);
        var targetTableColCount;
    
        //Loop through table rows
        for (var rowIndex = 0; rowIndex < targetTable.rows.length; rowIndex++) {
            var rowData = '';
    
            //Get column count from header row
            if (rowIndex == 0) {
                targetTableColCount = targetTable.rows.item(rowIndex).cells.length;
                continue; //do not execute further code for header row.
            }
    
            //Process data rows. (rowIndex >= 1)
            for (var colIndex = 0; colIndex < targetTableColCount; colIndex++) {
                rowData += targetTable.rows.item(rowIndex).cells.item(colIndex).textContent;
                rowData = rowData.toLowerCase();
            }
            console.log(rowData);
    
            //If search term is not found in row data
            //then hide the row, else show
            if (rowData.indexOf(searchText) == -1)
    
    
                targetTable.rows.item(rowIndex).style.display = 'none';
            else
                targetTable.rows.item(rowIndex).style.display = '';
        }
    }
    
        function _addTableDataRows(paramObjectTDR) {
        let { filterNode, limitNode, bodyNode, countNode, paramObject } = paramObjectTDR;
        let { dataRows, functionArray } = paramObject;
        _clearNode(bodyNode);
        if (typeof dataRows === `string`) {
            bodyNode.insertAdjacentHTML(`beforeend`, dataRows);
        } else {
            let filterTerm;
            if (filterNode) {
                filterTerm = filterNode.value.toLowerCase();
            }
            let serialNumber = 0;
            let limitNumber = 0;
            let rowNode;
            dataRows.forEach(currentRow => {
                if (!filterNode || _filterData(filterTerm, currentRow)) {
                    serialNumber++;
                    if (!limitNode || limitNode.value === `all` || limitNode.value >= serialNumber) {
                        limitNumber++;
                        rowNode = _getNode(`tr`);
                        bodyNode.appendChild(rowNode);
                        _addData(rowNode, serialNumber, currentRow, `td`);
                    }
                }
            });
            _clearNode(countNode);
            countNode.insertAdjacentText(`beforeend`, `Showing 1 to ${limitNumber} of ${serialNumber} entries`);
        }
        if (functionArray) {
            functionArray.forEach(currentObject => {
                let { className, eventName, functionName } = currentObject;
                _attachFunctionToClassNodes(className, eventName, functionName);
            });
        }
    }