首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如果某些<tr>不可见,则交替行颜色

如果某些<tr>不可见,则交替行颜色
EN

Stack Overflow用户
提问于 2015-09-24 15:49:56
回答 5查看 707关注 0票数 3

我有一个表,其中包含由foreach绑定生成的行。

与“通常”KO表的唯一区别是,对于行的动态筛选,我使用tr元素上的tr绑定,该绑定绑定到一个函数,该函数使用某些observables的值来决定当前行是否应该可见:

代码语言:javascript
复制
<table>
    <thead>
        ...
    </thead>
    <tbody data-bind="foreach: unfilteredItems">
        <tr data-bind="visible: $root.rowFilter($data)">
            ...
        </tr>
    </tbody>
</table>

我之所以使用这种方法,是因为与传统的foreach绑定集合操作相比,它的性能要好得多,并导致不断插入\删除DOM节点。

这里唯一的问题是,没有纯粹的CSS解决方案来交替行的颜色。-- tr节点停留在DOM中,当某些tr不可见时,:nth-child()选择器不能正常工作。

因此,我不得不坚持使用jQuery解决方案:

代码语言:javascript
复制
function stripeVisibleRows(tableElem) {
    var $visibleRows = $(tableElem).find('tr:visible');

    $visibleRows.filter(':odd').css('background-color', '#EEEAE7');
    $visibleRows.filter(':even').css('background-color', '#DED7D1');
};

但是,当visible rowFilter 使用的任何可观测值触发更新 visible 绑定时,在执行绑定之后,如何才能在Knockout中调用该函数?

根据subscribe函数的不同,我尝试了一个假的computed

代码语言:javascript
复制
self.rowFiltering = ko.computed(function () {
        return self.rowFilter();
    })
    .subscribe(function () {
        tableHelpers.stripeVisibleRows('.tbl');
    });

,编写这样的自定义绑定:

代码语言:javascript
复制
// Stripes visible tr elements.
// Must be applied to a table element. 
// Must be bound to the same expression as used to change visibility of the tr elements.
ko.bindingHandlers.stripeVisibleRows = {
    update: function (element, valueAccessor) {
        // Read provided binding value to establish dependencies tracking
        ko.utils.unwrapObservable(valueAccessor());

        tableHelpers.stripeVisibleRows(element);
    },
    after: ['visible']
};

以及它的用法:

代码语言:javascript
复制
<table data-bind="stripeVisibleRows: $root.rowFilter()">
    <thead>
        ...
    </thead>
    <tbody data-bind="foreach: unfilteredItems">
        <tr data-bind="visible: $root.rowFilter($data)">
            ...
        </tr>
    </tbody>
</table>

但是使用这两种方法,我的jQuery条带函数在应用visible绑定之前都会被调用,因此不能正常工作。

,有人能建议我如何实现我想做的事情吗?

--也许我甚至需要改变整个过滤和条带行的方法--,但是它不应该插入\删除DOM节点,并且尽可能干净和可重用。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2015-09-24 21:52:57

你不得不在幕后做任何事情,只需要通过函数来揭露它。可以使用CSS类完成条带处理,因此您不需要担心使用jQuery。

因为数据项不会改变,所以它们只是一个不可观察的数组。在幕后,我们有一个基于rowFilter的计算,它可以访问一些可观察到的。foreach调用查看与当前项对应的计算中的项的函数,以设置可见性和类。

在本例中,您将根据元素的字母数对其进行过滤。

代码语言:javascript
复制
var tracker;

vm = {
  letters: ko.observable(3),
  unfilteredItems: ['One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten'],
  visible: function(idx) {
    return tracker()[idx].visible;
  },
  odd: function(idx) {
    return tracker()[idx].odd;
  }
};

function rowFilter(item) {
  return item.length === vm.letters();
}

tracker = ko.pureComputed(function() {
  var visibleCount = 0;
  var result = ko.utils.arrayMap(vm.unfilteredItems, function(item) {
    var visible = rowFilter(item);
    if (visible) ++visibleCount;
    return {
      visible: visible,
      odd: visibleCount % 2
    };
  });
  return result;
});

ko.applyBindings(vm);
代码语言:javascript
复制
tr {
  background-color: lightgreen;
}
tr.odd {
  background-color: yellow;
}
代码语言:javascript
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<select data-bind="value:letters, options:[3,4,5]"></select>
<table border="1">
  <tbody data-bind="foreach: unfilteredItems">
    <tr data-bind="visible: $root.visible($index()) , css: {odd:$root.odd($index())} ">
      <td data-bind="text:$data"></td>
    </tr>
  </tbody>
</table>

票数 2
EN

Stack Overflow用户

发布于 2015-09-24 15:55:43

您可以订阅rowFilter的更改,然后推迟对stripeVisibleRows调用的执行,以确保模式已经更新了所有内容。

代码语言:javascript
复制
self.rowFilter.subscribe(function() {
    setTimeout(function() {
        tableHelpers.stripeVisibleRows('.tbl');
    }, 0);
});

对于不介意从DOM中删除/添加元素的情况,可以使用绑定而不是visible --这将完全从DOM中删除标记,而不只是隐藏它:

代码语言:javascript
复制
<table>
    <thead>
        ...
    </thead>
    <tbody data-bind="foreach: unfilteredItems">
        <tr data-bind="if: $root.rowFilter($data)">
            ...
        </tr>
    </tbody>
</table>
票数 2
EN

Stack Overflow用户

发布于 2015-09-24 16:38:53

与其计算表呈现后的所有行条(即:使用stripeVisibleRows),不如将当前循环$index传递给一个单独的$root函数,让它确定该索引的当前条带是什么。例如:

Html:

代码语言:javascript
复制
<style>
  .On { background-color: #CCC }
  .Off { background-color: #FFF }
</style>

<table id='test'>
    <thead>
        ...
    </thead>
    <tbody data-bind="foreach: unfilteredItems">
        <tr data-bind="visible: IsVisible, css: $root.rowColour($index)">
            <td data-bind='text: Text'></td>
        </tr>
    </tbody>
</table>

Javascript:

代码语言:javascript
复制
var vmItem = function(visible, text) {
    this.IsVisible = visible;
  this.Text = text;
}

var vm = {
    unfilteredItems: [
        new vmItem(true, "Some"),
        new vmItem(true, "Data"),
        new vmItem(false, "Not Shown"),
        new vmItem(true, "Shown"),
        new vmItem(true, "To"),
        new vmItem(false, "Blah!"),
        new vmItem(true, "The User")
    ],
    rowColour: function(index) {
    var toggle = true;
        for(var c = 0; c < index(); c++) {
      // if the row at this index is visible, flip the row toggle
      if (this.unfilteredItems[c].IsVisible) toggle = !toggle;
    }
    return toggle ? "On" : "Off";
    }
};

ko.applyBindings(vm, $('#test')[0]);

示例CodePen

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32765718

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档