使用knockout

时间:2016-05-24 12:27:05

标签: javascript jquery knockout.js

有没有办法将数组元素绑定为输入值或选择?

像这样......

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

  self.array = ko.observableArray([undefined, undefined, undefined]);

  self.text = ko.computed(function() {
    return self.array()[0] + self.array()[1] + self.array()[2];
  });
}

var viewModel = new ViewModel();
ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<input data-bind="value: $root.array[0]" />
<input data-bind="value: $root.array[1]" />
<input data-bind="value: $root.array[2]" />
<p data-bind="text: $root.text"></p>

修改

对不起伙计们,我提出问题真的很糟糕,但是我的问题有点棘手,我的真实条目是选择,它是数组的过滤器和选择的值。像这样:

var ViewModel = function() {
  var self = this;
  self.family = ko.mapping.fromJS(data.family);

  self.array = ko.observableArray([ko.observable(undefined), ko.observable(undefined), ko.observable(undefined)]);

  self.filterFamily1 = function() {
    return self.family().filter(function(i) {
      return i.parent() == null;
    });

  }
  self.filterFamily2 = ko.computed(function() {
    return ko.utils.arrayFilter(self.family, function(i) {
      return i.parent() === self.array()[0]().name();
    });

  });
   self.filterFamily3 = ko.computed(function() {
    return ko.utils.arrayFilter(self.family, function(i) {
      return i.parent() === self.array()[1]().name();
    });

  })

}

var data = {
  family: [{
    name: "John",
    parent: null
  }, {
    name: "Mary",
    parent: null
  }, {
    name: "Erick",
    parent: "John"
  }, {
    name: "Paul",
    parent: "John"
  }, {
    name: "Marshall",
    parent: "Mary"
  }, {
    name: "Ross",
    parent: "Paul"
  }]
};

var viewModel = new ViewModel();
ko.applyBindings(viewModel);
<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>

<select data-bind="options: $root.filterFamily1(),optionsText: 'name', value: $root.array()[0]"></select>
<select data-bind="options: $root.filterFamily2(),optionsText: 'name', value: $root.array()[1]"></select>
<select data-bind="options: $root.filterFamily3(),optionsText: 'name', value: $root.array()[2]"></select>

但答案适合我之前描述的问题。

3 个答案:

答案 0 :(得分:4)

由于您的问题发生了很大变化,我发布了一个新答案:

您的代码段有控制台错误:您最初选择的值未设置,也未检查未定义。包括这些检查,一切正常。

请注意,您绝对可以提高可读性并重构重复的代码段。

aggregateByKey
var ViewModel = function() {
  var self = this;
  self.family = ko.mapping.fromJS(data.family);




  self.filterFamily1 = ko.computed(function() {
    return self.family().filter(function(i) {
      return i.parent() === null;
    });

  });

  self.array = ko.observableArray([
    ko.observable(self.filterFamily1()[0]),
    ko.observable(undefined),
    ko.observable(undefined)
  ]);

  self.filterFamily2 = ko.computed(function() {
    return self.family().filter(function(i) {
      return self.array()[0]() && i.parent() === self.array()[0]().name();
    });

  });
  self.filterFamily3 = ko.computed(function() {
    return self.family().filter(function(i) {
      return self.array()[1]() && i.parent() === self.array()[1]().name();
    });

  })

}

var data = {
  family: [{
    name: "John",
    parent: null
  }, {
    name: "Mary",
    parent: null
  }, {
    name: "Erick",
    parent: "John"
  }, {
    name: "Paul",
    parent: "John"
  }, {
    name: "Marshall",
    parent: "Mary"
  }, {
    name: "Ross",
    parent: "Paul"
  }]
};

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

答案 1 :(得分:3)

Yessir,当然有。但是:

  1. 项目本身必须为observable s。
  2. 您应该在绑定到其中一个元素之前执行self.array函数。
  3. 以下是一个例子:

    var ViewModel = function() {
      var self = this;
    
      self.array = ko.observableArray([ko.observable(""), ko.observable(""), ko.observable("")]);
    
      self.text = ko.computed(function() {
        return self.array()[0]() + self.array()[1]() + self.array()[2]();
      });
    }
    
    var viewModel = new ViewModel();
    ko.applyBindings(viewModel);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
    <input data-bind="value: $root.array()[0]" />
    <input data-bind="value: $root.array()[1]" />
    <input data-bind="value: $root.array()[2]" />
    <p data-bind="text: $root.text"></p>

    但是,为什么不使用foreach绑定和其他一些不错的改进?

    var ViewModel = function() {
      var self = this;
    
      self.array = ko.observableArray([
        { txt: ko.observable("a") },
        { txt: ko.observable("b") },
        { txt: ko.observable("c") },
        { txt: ko.observable("d") }
      ]);
    
      self.text = ko.computed(function() {
        return self.array().map(function(obs) { return obs.txt(); }).join("");
      });
    }
    
    var viewModel = new ViewModel();
    ko.applyBindings(viewModel);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
    
    <!-- ko foreach: array -->
    <input data-bind="textInput: txt">
    <!-- /ko -->
    <p data-bind="text: text"></p>

答案 2 :(得分:2)

如果要按索引访问数组,则需要先使用()评估observable。

如果您希望value绑定以双向方式工作(即:不仅最初设置它,还要在更改后更新viewmodel中的值),您必须将它们绑定到{{ 1}}变量。

其他改进:

如果您想将所有值加在一起,可以使用ko.observablereducemap的组合来附加字符串。

编辑:我错了! 如果需要输入所有数组的值,也可以使用join绑定并使用foreach来引用当前值。

实际上,您无法使用$data关键字创建双向绑定。如果您使用$data observable。

,则可以

参考:https://github.com/knockout/knockout/issues/708

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

  self.array = ko.observableArray([ko.observable("a"), ko.observable("b"), ko.observable("c")]);

  self.text = ko.computed(function() {
    return self.array()[0]() + self.array()[1]() + self.array()[2]();
  });

  self.reducedText = ko.computed(function() {
    return self.array()
      .reduce(function(prev, curr) {
        return prev + curr();
      }, "");

  });
};

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