javascript - 使用 Knockout 将项目添加到列表后更改背景颜色

标签 javascript jquery knockout.js

我正在尝试创建一个表格,其中新项目将以不同的背景颜色显示。下面的示例显示了我正在做的事情。

var data = [{
  name: "Gibson",
  id: "1"
}, {
  name: "Fender",
  id: "2"
}, {
  name: "Godin",
  id: "3"
}, {
  name: "Tagima",
  id: "4"
}, {
  name: "Giannini",
  id: "5"
}];

var list = [{
  name: "Gibson",
  id: "1"
}, {
  name: "Fender",
  id: "2"
}];

var ViewModel = function() {
  var self = this;

  self.mylist = ko.mapping.fromJS(list);
  self.data = ko.mapping.fromJS(data);
  self.selectedItem = ko.observable(undefined);

  self.addItem = function() {
    if (self.selectedItem == undefined) return;
    self.mylist.push(self.selectedItem());
    $("#" + self.selectedItem().id()).addClass("newItem");
    self.selectedItem(undefined);
  }
}

var viewModel = new ViewModel();
ko.applyBindings(viewModel);
.newItem {
  background-color: #DCEDC1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>

<select data-bind="options: $root.data, optionsText: 'name', optionsCaption: 'Select yout Guitar', value: selectedItem, event:{change: $root.addItem}"></select>

<table>
  <thead>
    <tr>
      <th>
        <p>
          Guitars
        </p>
      </th>
    </tr>
  </thead>
  <tbody data-bind="foreach:mylist">
    <tr data-bind="attr:{id: $data.id}">
      <td>
        <p data-bind="text: $data.name"></p>
      </td>
    </tr>
  </tbody>
</table>

但在某些 View 中,表中的新行是在函数 addItem 完成后添加的,因此背景颜色不会改变。有其他方法可以做到这一点或解决此问题吗?

最佳答案

如果您还使用 knockout ,那么使用 jQuery 来跟踪类将会很困难。如果您的吉他对象保持简单,您可以用很少的代码实现您的功能(如果您不想,则不必创建新的 View 模型)。这是您需要做的:

  1. 跟踪数组中的所有新项目
  2. 对于每个项目,确定他们是否需要 .isNew通过检查它们是否在此数组中来定义类
  3. 使用 css 切换类绑定(bind)

第 1 步:

内部ViewModel您可以创建第三个 observableArraymyList仍然存储所有选定的项目,新数组 newItems仅存储 id通过 UI 添加的项目的属性。

第 2 步:

addItem方法,我们不是通过 jQuery 选择元素并添加类,而是将新项目推送到 newItems数组。

第 3 步:

替换 attrcss 绑定(bind)绑定(bind)创建一个计算 bool 值来指示该行是否是新的:

<tr data-bind="css:{'newItem' : guitarIsInArray($data, $parent.newItems())}">

附加说明:

  • 您正在使用selectedValue存储 <select>元素的更改:最好订阅该值的更改,而不是通过 event: { change: fn } 创建另一个事件监听器
  • 由于您的吉他只是普通物体,data 中的Gibson数组将不等于 myList 中的 Gibson 。我创建了一个辅助方法来确保您不会获得重复的值 ( guitarIsInArray )。
  • 最终,即使您没有创建 Guitar viewmodel,我会尝试确保代码中每把吉他只有一个对象引用。

这是一个更新的示例:

var data = [{
  name: "Gibson",
  id: "1"
}, {
  name: "Fender",
  id: "2"
}, {
  name: "Godin",
  id: "3"
}, {
  name: "Tagima",
  id: "4"
}, {
  name: "Giannini",
  id: "5"
}];

var list = [{
  name: "Gibson",
  id: "1"
}, {
  name: "Fender",
  id: "2"
}];



var ViewModel = function() {
  var self = this;

  self.data = ko.mapping.fromJS(data);
  self.mylist = ko.mapping.fromJS(list);

  self.newItems = ko.observableArray([]);

  // This excludes any guitar in mylist from data
  self.unusedData = ko.computed(function() {
    return self.data().filter(function(guitar) {
      return !guitarIsInArray(guitar, self.mylist());
    });
  });

  self.selectedItem = ko.observable();

  // Called whenever your select changes
  self.selectedItem.subscribe(function(newItem) {
    if (!newItem || guitarIsInArray(newItem, self.mylist())) {
      return;
    }

    self.mylist.push(newItem);
    self.newItems.push(newItem);
  });
}

var viewModel = new ViewModel();
ko.applyBindings(viewModel);

function guitarIsInArray(guitar, array) {
  for (var g = 0; g < array.length; g += 1) {
    if (array[g].id() === guitar.id()) {
      return true;
    }
  }

  return false;
};
.newItem {
  background-color: #DCEDC1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>

<select data-bind="options: $root.unusedData, optionsText: 'name', optionsCaption: 'Select your Guitar', value: selectedItem"></select>

<table>
  <thead>
    <tr>
      <th>
        <p>
          Guitars
        </p>
      </th>
    </tr>
  </thead>
  <tbody data-bind="foreach:mylist">
    <tr data-bind="css:{'newItem' : guitarIsInArray($data, $parent.newItems())}">
      <td>
        <p data-bind="text: $data.name"></p>
      </td>
    </tr>
  </tbody>
</table>

关于javascript - 使用 Knockout 将项目添加到列表后更改背景颜色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37596770/

相关文章:

javascript - Knockoutjs div 绑定(bind)未按预期工作

javascript - 如何在功能组件 React Native 中删除 Header

javascript - 如何使用 requirejs 使 jQuery 插件可加载

javascript - 为什么切换不能与其他 DIV 一起使用?

javascript - 捕获 jQuery UI 日期选择器中的值并将其提醒给用户

javascript - 解压属性后,Knockout 停止更新 observable

javascript - Canvas 宽度和高度 - webview

javascript - 如何重定向到其他页面并在点击时动态加载相应id的内容

javascript - 获取对象类型

javascript - 使用knockout.js从选择列表中检索值