通过jQuery事件处理程序更新Knockout observable

时间:2016-08-08 03:12:04

标签: javascript jquery arrays json knockout.js

据我所知,使用带有Knockout的jQuery事件处理程序是不好的做法,但目前我想继续这条路径。我正在寻找有关如何使用jQuery中的click事件更新视图模型的说明,正如我在this Fiddle中所述。

预期的行为是:单击颜色按钮(即Red, Green, Blue),然后单击UPDATE!以显示相应颜色的数据。例如,单击红色 - >更新将在DOM中吐出“红花太阳”。然后点击蓝色 - >更新将产生“蓝天海洋”。

我认为问题在于我的observable和with: colors数据绑定,但我不完全理解为什么。对于我来说,这基本上是针对Knockout的为期2天的速成课程,我觉得这应该比它更容易实现。

请告诉我光明!

HTML

<div data-bind="with: colors">
  <h4 data-bind="text: name"></h4>
  <div data-bind="foreach: things">
    <span data-bind="text: $data" />
  </div>
</div>

的JavaScript

function Sample(data) {
  var self = this;

  self.colors = ko.observableArray();
  self.currentColor = ko.observable();

  ko.mapping.fromJS(data, {}, self);
}

var sample = new Sample({
  "colors": [{
    "name": "red",
    "things": ["flower", "sun"]
  }, {
    "name": "green",
    "things": ["tree", "money"]
  }, {
    "name": "blue",
    "things": ["sky", "ocean"]
  }]
});

ko.applyBindings(sample);

var clicked;
$("button").on("click", function() {
  clicked = this.className;
});

$(".update").on("click", function() {
  if (clicked === "red") {
    // ???    
  }
  if (clicked === "green") {
    // ???    
  }
  if (clicked === "blue") {
    // ???    
  }
});

2 个答案:

答案 0 :(得分:1)

我更新了你的小提琴,以匹配你想要的东西。 但我希望你真的会忽视这种方式。 请检查此fiddle

我所做的是找到name变量clicked的颜色。

$(".update").on("click", function() {
  var foundColor = sample.colors().find(function(color){
    return color.name() === clicked;
  });
  sample.currentColor(foundColor);
});

你的with binding的值应该是currentColor,而不是你的可观察数组。

<div data-bind="with: currentColor">

但是,这不是正确的方法,你应该阅读click绑定,它会让你开始,并将有一个更清洁的实现,而且更短。

答案 1 :(得分:1)

如果要渲染所有颜色,则必须使用foreach绑定。这有点像with数组中每个项目的自动colors绑定:

<div data-bind="foreach: colors"> ... </div>

我不认为你在使用淘汰赛时应该使用jQuery进行处理,所以我将解释如何使用click绑定。

点击装订的基本布局是:

click: function(currentlyBoundData, event) { /* ... */ }

这意味着,当您使用foreach绑定时,它会将点击的数据与点击事件一起发送。

让我们首先在您的viewmodel中添加一个点击处理程序:

self.clickHandler = function(clickedItem, event) {
  console.log(clickedItem);
};

现在,将此处理程序方法附加到每种颜色的点击:

<div data-bind="foreach: colors">
  <h4 data-bind="text: name, click: $parent.clickHandler"></h4>
</div>

注意$parent:它链接到foreach级别的数据绑定上下文,即Sample视图模型。

现在你已经制作了一个可以被所有颜色重用的方法,你可以编写其余的逻辑代码:

  1. 知道通过向其传递参数来设置observable,
  2. 并且知道click绑定将点击的项目作为第一个参数传递
  3. 我们可以直接将observable绑定到click方法

    1. 喜欢这样:data-bind="click: $parent.currentColor"
    2. 最后,您需要一个update方法:

      1. 通过不带参数调用currentColor
      2. 来获取self.currentColor()
      3. 并将其放入一个名为selectedColorself.selectedColor(self.currentColor())
      4. 的新观察中

        function Sample(data) {
          var self = this;
        
          self.colors = ko.observableArray();
          self.currentColor = ko.observable();
          self.selectedColor = ko.observable();
        
          self.updateColor = function() {
            self.selectedColor(self.currentColor());
          };
        
          ko.mapping.fromJS(data, {}, self);
        }
        
        var sample = new Sample({
          "colors": [{
            "name": "red",
            "things": ["flower", "sun"]
          }, {
            "name": "green",
            "things": ["tree", "money"]
          }, {
            "name": "blue",
            "things": ["sky", "ocean"]
          }]
        });
        
        ko.applyBindings(sample);
        .selected {
          background: yellow;
        }
        <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
        
        <div data-bind="foreach: colors">
          <h4 data-bind="text: name, click: $parent.currentColor, css: {'selected' : $parent.currentColor() === $data}"></h4>
        </div>
        
        <button data-bind="click: updateColor">load last clicked</button>
        
        <div data-bind="with: selectedColor">
          Selection: <strong data-bind="text: name"></strong>
        </div>