【问题标题】:How to call Knockout bindingHandler->Update after DOM is updatedDOM更新后如何调用Knockout bindingHandler->Update
【发布时间】:2013-08-07 01:23:31
【问题描述】:

我在 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>

CodePen

【问题讨论】:

  • 我添加了一个演示。有什么问题?它似乎有效。
  • 不是真的,手风琴创建了 UI 类,但事件没有绑定。

标签: ajax jquery-ui knockout.js bindinghandlers


【解决方案1】:

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

【讨论】:

  • “如果你坚持自定义绑定”VM 中的 AfterRender 和 DOM 依赖是一种反模式,所以自定义绑定要好得多
  • 太好了,现在,我必须添加一些代码才能在渲染最后添加的项目时绑定手风琴
【解决方案2】:
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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-03
    • 2014-04-27
    • 2012-08-28
    • 2012-02-29
    • 1970-01-01
    • 2016-06-15
    • 2013-12-06
    • 2012-12-30
    相关资源
    最近更新 更多