2

我在 KO bindingHandler 中使用 jquery 手风琴,我必须填充手风琴 UI 使用的 DOM,根据应用程序要求使用 ajax。

this.faqList = ko.observableArray();
$.ajax({
  url: 'getFaqs'
}).done(function( data ) {
  that.faqList(data);
});

我的 bindingHandler 应该像

ko.bindingHandlers.koAccordion = {
  init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
    $(element).accordion(valueAccessor());

  },
  update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
      $(element).accordion(valueAccessor());
  }
};

当 observableArray (faqList) 发生变化时调用 update 方法,但此时 UI 手风琴需要已经填充的 DOM 结构,这是不正确的,似乎 KO 在调用 update 方法后创建。在 DOM 结构中填充新内容后,如何实现调用更新?

这是默认的 DOM。

<ul class="question-list" data-bind="koAccordion: {
          active: false,
          autoHeight: false, 
          collapsible: true}">
  <!-- ko foreach: faqList -->
    <li>
      <div class="header">
        <span class="rigth-arrow"></span>
        <a href="#" data-bind="text: title"></a>
      </div>
      <div class="content">
        <h2 data-bind="text: title"></h2>
        <div data-bind="text: content"></div>
      </div>
    </li>
  <!-- /ko -->
  </ul>

代码笔

4

2 回答 2

3

koAccordion.update没用,因为您永远不会更新该绑定值:它在标记中是静态的,并且不包含任何可观察值。foreach绑定afterRender为您的目的提供回调:

var vm = function() {
    // ...
    this.initAccordion = function(element) {
        $(element).accordion(accordionOptions);
    };
};


<!-- ko foreach: { data: faqList, afterRender: initAccordion } -->

但是,在这种情况下,您必须将手风琴选项移出绑定值。如果您坚持使用自定义绑定,一种方法是将工作委托给foreach绑定,afterRender并在途中插入绑定值:

ko.bindingHandlers.koAccordion = {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel,
                   bindingContext) {
        var newValue = ko.computed(function() {
            var value = ko.unwrap(valueAccessor());
            value.afterRender = function(element) {
                $(element).accordion(value);
            };
            return value;
        });
        return ko.bindingHandlers.foreach.init(element, newValue,
            allBindingsAccessor, viewModel, bindingContext);
    },
    update: function(element, valueAccessor, allBindingsAccessor, viewModel,
                     bindingContext) {
        return ko.bindingHandlers.foreach.update(element, valueAccessor,
            allBindingsAccessor, viewModel, bindingContext);
    }
};

像这样使用它:

<ul class="question-list" data-bind="koAccordion: {
      data: faqList,
      active: false,
      autoHeight: false, 
      collapsible: true }">
   <li>...bindings...</li>
</ul>

请参阅我从帖子中的一个分叉的演示页面:http: //codepen.io/anon/pen/IJpuj

于 2013-08-07T05:19:42.040 回答
1
This is my final code
ko.bindingHandlers.koAccordion = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
  var newValue = ko.computed(function() {
    var value = ko.unwrap(valueAccessor());
    value.afterRender = function(renderedElement, loopEntryObject) {
      if ( loopEntryObject == value.data()[value.data().length - 1] ) {
        if ($(element).data('accordion')) {
          $(element).accordion('destroy');
        }
        $(element).accordion(value);
      }
    };
    return value;
  });
  return ko.bindingHandlers.foreach.init(element, newValue, allBindingsAccessor, viewModel, bindingContext);
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
  return ko.bindingHandlers.foreach.update(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
}
于 2013-08-07T18:37:46.377 回答