Knockout viewmodel 函数只影响最后一个实例

Knockout viewmodel function affects only the last instance

我试图实现的是实例化多个视图模型(数量是可变的)但是无论我从哪里点击,点击时绑定的函数只会影响最后一个实例。

JS

function Photo(name){
    var self = this;
    self.name = name;
}

function SectionPhotosViewModel() {
    var self = this;  

    // Editable data
    self.photos = ko.observableArray([
        {
            name: 'smth'
        },
        {
            name: 'smth else'
        }
    ]);

    // Operations
    self.addPhoto = function() {
        self.photos.push(new Photo('anything'));
    }
}

function bindSectionPhotos(element, index, list){
    ko.applyBindings(SectionPhotosViewModel, element);
}

_.each(document.querySelectorAll( 'fieldset.room' ), bindSectionPhotos)

HTML

<fieldset class="room">
    <div data-bind="click: addPhoto;" class="btn btn-success">Add new</div>
    <ul data-bind="foreach: photos">
        <li data-bind="text: name"></div>
    </ul>
</fieldset>
<fieldset class="room">
    <div data-bind="click: addPhoto;" class="btn btn-success">Add new</div>
    <ul data-bind="foreach: photos">
        <li data-bind="text: name"></div>
    </ul>
</fieldset>
<fieldset class="room">
    <div data-bind="click: addPhoto;" class="btn btn-success">Add new</div>
    <ul data-bind="foreach: photos">
        <li data-bind="text: name"></div>
    </ul>
</fieldset>
<fieldset class="room">
    <div data-bind="click: addPhoto;" class="btn btn-success">Add new</div>
    <ul data-bind="foreach: photos">
        <li data-bind="text: name"></div>
    </ul>
</fieldset>

无论我点击什么按钮,只有最后一次被修改。想法?建议?

您有一个 constructor 函数,您引用时没有使用 new 关键字,因此总是引用函数定义。试试这个:

function bindSectionPhotos(element, index, list){
    ko.applyBindings(new SectionPhotosViewModel(), element);
}

这是一个完整的演示:

function Photo(name) {
  var self = this;
  self.name = name;
}

function SectionPhotosViewModel() {
  var self = this;

  self.photos = ko.observableArray([
    { name: 'smth' }, 
    { name: 'smth else' }]);

  self.addPhoto = function() {
    self.photos.push(new Photo('anything'));
  }
}

function bindSectionPhotos(element, index, list) {
  ko.applyBindings(new SectionPhotosViewModel(), element);
}

_.each(document.querySelectorAll('fieldset.room'), bindSectionPhotos)
.btn { background: #eee; padding: 5px; cursor: pointer; display: inline-block; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>

<fieldset class="room">
  <div data-bind="click: addPhoto;" class="btn btn-success">Add new</div>
  <ul data-bind="foreach: photos">
    <li data-bind="text: name"></li>
  </ul>
</fieldset>
<fieldset class="room">
  <div data-bind="click: addPhoto;" class="btn btn-success">Add new</div>
  <ul data-bind="foreach: photos">
    <li data-bind="text: name"></li>
  </ul>
</fieldset>
<fieldset class="room">
  <div data-bind="click: addPhoto;" class="btn btn-success">Add new</div>
  <ul data-bind="foreach: photos">
    <li data-bind="text: name"></li>
  </ul>
</fieldset>