【问题标题】:BindingHandler in Knockoutjs. build own ListViewKnockoutjs 中的 BindingHandler。构建自己的 ListView
【发布时间】:2012-06-14 20:17:57
【问题描述】:

我想用 selectedItem 和 Itemsource 构建自己的 listView。

我已经启动了一个 jsFiddle http://jsfiddle.net/andersb79/53xRL/1/

请您帮助我了解我应该如何构建它。 我还没有看到能做到这一点的 bindingHanlder。

我想要的是这样的。

data-bind="myListView : { items : comments, selectedItem : selectedComment}"

【问题讨论】:

    标签: jquery knockout.js


    【解决方案1】:

    在您的自定义绑定中,您需要:

    1. 为列表中的每个项目创建一个元素
    2. 将该元素附加到父元素
    3. 为在原始视图模型上设置 selectedItem 的每个元素添加一个单击处理程序

    为了清楚起见,我还突出显示了当前选定的项目。

    ko.bindingHandlers.myListView = {
        update: function(element, valueAccessor) {
            var value = ko.utils.unwrapObservable(valueAccessor()),
    
                //get the list of items
                items = value.items(),
                //get a reference to the selected item observable
                selectedItem = value.selectedItem,
                //get a jQuery reference to the element
                $element = $(element),
                //get the currently selected item
                currentSelected = selectedItem();
    
            //clear the parent of any existing children
            $element.html("");
    
            for (var index = 0; index < items.length; index++) {
                (function() {
                    //get the list of items
                    var item = ko.utils.unwrapObservable(items[index]),
    
                        //create a child element with a click handler
                        $childElement = $("<li>")
                        .text(item.id() + " " + item.text())
                        .click(function() {
                            //remove selected class on all siblings
                            $(this).siblings().removeClass("selected");
                            //add selected class on this item
                            $(this).addClass("selected");
                            //set the observable 'selected item' property on the source view model
                            selectedItem(item);
                        });
    
                    //add the selected class if this item is the current selected item
                    if (item == currentSelected) {
                        $childElement.addClass("selected");
                    }
    
                    //add the child to the parent
                    $element.append($childElement);
                })();
            }
    
        }
    };
    

    这是working example

    注意:由于我使用的是 update 而不是 init 方法,因此它在更新 cmets 列表时会起作用

    更新

    如果要使用原始 DIV 的内容作为每个创建项目的模板,则需要两个额外的步骤:

    1. 在初始化时获取元素的原始内容,并使用它来代替上面的硬编码内容
    2. 在将创建的元素添加到 DOM 之前对其应用绑定

          ko.bindingHandlers.myListView = {
      init: function(element) {
          var $element = $(element),
              originalContent = $element.html();
      
          $element.data("original-content", originalContent);
          return { controlsDescendantBindings: true }
      },
      update: function(element, valueAccessor) {
          var value = ko.utils.unwrapObservable(valueAccessor()),
      
              //get the list of items
              items = value.items(),
              //get a reference to the selected item observable
              selectedItem = value.selectedItem,
              //get a jQuery reference to the element
              $element = $(element),
              //get the currently selected item
              currentSelected = selectedItem(),
              //get the current content of the element
              elementContent = $element.data("original-content");
      
          $element.html("");
      
          for (var index = 0; index < items.length; index++) {
              (function() {
                  //get the list of items
                  var item = ko.utils.unwrapObservable(items[index]),
      
                      //create a child element with a click handler
                      $childElement = $(elementContent)
                      .click(function() {
                          //remove selected class on all siblings
                          $(this).siblings().removeClass("selected");
                          //add selected class on this item
                          $(this).addClass("selected");
                          //set the observable 'selected item' property on the source view model
                          selectedItem(item);
                      });
      
                  ko.applyBindings(item, $childElement[0]);
      
                  //add the selected class if this item is the current selected item
                  if (item == currentSelected) {
                      $childElement.addClass("selected");
                  }
      
                  //add the child to the parent
                  $element.append($childElement);
              })();
          }
      
      }
      

      };

    请注意,我们必须通过从 init 方法返回 { controlsDescendantBindings: true } 来防止 div 的内容被敲除处理。

    这是updated example

    【讨论】:

    • 非常感谢。但是,如果我想成为 abel 在 div 中包含注释或模板的代码怎么办。
      在页面上我想要这里的代码是一个评论。所以我可以在这里做 data-bind="text:comment"
    • 帮助很大。你不能连接并使用 bindinghandler 中的 foreach 绑定来利用模板绑定,所以如果我想要这样的话。 myListView : {Items : Comment,template : 'myTemplate',selectedItem : selectedItem} 并且没有 for 循环,而是有一个淘汰赛 foreach。可能吗?好点了吗?
    • 这是可能的,而且可以说更好,因为我们在这里稍微重写了淘汰赛功能
    • 在你的例子中,我怎样才能让 $parent 成为 div 内的 viewModel 以便我可以进行删除和更新,现在在 div 中 $parent 也是一个评论。
    • 对于这个给定的解决方案,如果我想在项目在 DOM 中呈现后添加自定义方法,我将如何做呢?似乎它应该在方法的更新部分,但我应该订阅什么事件?这与另一个 question: 相关联
    猜你喜欢
    • 1970-01-01
    • 2014-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-24
    • 2019-05-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多