50

私はノックアウト.jsを使用して動的リストを作成しています。監視可能な配列内のオブジェクトに関連付けられたDOMオブジェクトを取得する方法を見つけようとしています。具体的には、行の jQuery を取得したいと考えています。

例:

<ul data-bind="foreach: Item">
    <li data-bind="events: {click: getDomObject}, text: 'text: ' + text">
    </li>
</ul>

getDomObject関数では、特定の DOM オブジェクトを取得できるようにして、それ<li></li>を使用して jQuery 操作を実行できるようにしたいと考えています。

Item ViewModel にメンバーを追加し、id を項目の html id として追加し、それに基づいて選択することを考えidましたが、もっと簡単な方法があるはずだと感じています。

ノックアウト.jsによって生成された動的HTMLを参照する適切な方法は何ですか?

4

5 に答える 5

67

click get などのイベント ハンドラーには、2 つの引数が渡されます。あれは

  1. このイベントが属するアイテム - foreach バインディングでレンダリングしている監視可能な配列のエントリのように (この場合は「アイテム」)。

  2. そして、実際のイベントに関する詳細情報を提供するイベント オブジェクト。このオブジェクトには、クリックされた DOM 要素 (キー「ターゲット」) が含まれています。

    getDomObject = function(item, event) {
        var $this = $(event.target);
        // ...
    }
    

注意: ノックアウトとネイティブの jQuery DOM 操作を混在させないでください。巧妙なノックアウト バインディングで同じ結果が得られる場合は、それを使用することをお勧めします。

ここに簡単なデモがあります: http://jsfiddle.net/KLK9Z/213/

var Item = function(color) {
  this.color = String(color);
  this.setTextColor = function(item, event) {
    $(event.target).css('background', color);
  };
};

ko.applyBindings(new function() {
  this.Items = ko.observableArray([
    new Item('red'),
    new Item('blue'),
    new Item('green')
  ]);
}());
li {
  padding: 2px 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/2.0.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<ul data-bind="foreach: Items">
  <li>
    <button data-bind="click: setTextColor, text: 'Color: ' + color"></button>
  </li>
</ul>

于 2012-04-12T15:42:10.243 に答える
20

$(event.target)ソリューションは、アイテムの DOM 要素がターゲットにある、既に発生しているイベントに関連している場合に適しています。しかし、イベントがないために目的のアイテムがない場合があります (たとえば、ユーザーがジェスチャしていないアイテムにリストをスクロールしたい場合など)。

このような場合、アイテムの DOM 要素の id 属性に、アイテム ID を含む一意の値を指定できます。

<li data-bind="attr: {id: 'item_' + id}">

getDomObject() は次のようになります。

getDomObject = function(item) { return $("#item_" + item.id); }
于 2012-08-22T09:24:03.057 に答える
7

さらに3番目のオプションを追加するには、使用するイベントがない場合も同様です(イベントがある場合は、受け入れられた回答が最適/最適化されます)。

次のようなカスタムバインディングを作成します。

ko.bindingHandlers.scrollTo = {
    update: function(element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor());
        if (value) {
            var scrollParent = $(element).closest("div");
            var newTop = $(element).position().top + scrollParent.scrollTop();
            scrollParent.scrollTop(newTop);
        }
    }
};

使用法は次のとおりです。

<li data-bind="scrollTo: $parent.scrollTo() && $parent.scrollTo().id == id">

上記の場合、$parentは私のビューモデルです。一意のIDを含む監視可能なオブジェクトがあります。そのscrollTo()オブジェクトを設定すると、リストはそのアイテムにスクロールします。

私のコードは、LIの親DIVにスクロールバー(overflow:auto / scroll)があることを前提としていることに注意してください。ニーズに合わせて調整したり、親のクラスを使用してjQueryセレクターに使用したり、データバインドオプションを介してセレクターを渡すことができるようにすることもできます...私にとっては、これで十分でした。スクロール可能なセクションには常にdivを使用します。

于 2013-02-18T03:49:38.607 に答える
5

同様の問題がありました。Backbone.js での el および $el 参照の使用に似たソリューションを考え出しました。

あなたのViewModelで:

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

  //html element
  self.el = ko.observable();

  //jquery wrapped version
  self.$el = ko.observable();
}

HTML 内 (たとえば、リスト要素):

<!-- left side is the name of the handler, right side is name of the observable -->
<li class="myclass" data-bind="el: el, $el: $el"></li>

bindingHandlers 内 (init に可能なすべての引数を表示):

ko.bindingHandlers.el = {
  init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
    var value = valueAccessor();
    //assign value to observable (we specified in html)
    value(element);
  }
};

ko.bindingHandlers.$el = {
  init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
    var value = valueAccessor();
    //here we first create a jQuery object by using $(myelem)
    //before updating observable value
    value($(element).first());
  }
};

たとえば、次のように $el を使用できます。

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

  //plain DOM element reference
  self.el = ko.observable();

  //jquery object reference
  self.$el = ko.observable();

  self.myFunction = function() {
    console.log(self.$el().html());
    self.$el().addClass("myCssClass");
  }
}

お役に立てれば!

于 2015-12-29T09:45:26.047 に答える