为组件设置 viewModel = $data

Set viewModel = $data for Component

我刚刚开始了解 Knockout Components。现在我正在尝试创建一个 "Template Only" 组件。我 运行 遇到的问题是将组件的 viewmodel 设置为我使用该组件的 $data。我修改了 Knockout 页面中的示例 (http://knockoutjs.com/documentation/component-overview.html)

这是一个展示我所做的事情的小插曲:http://plnkr.co/edit/23PVEW9aQ63A9yq2wRJp

我在 foreach 中使用该组件,例如:

  <ul data-bind="foreach: products">
    <li class="product">
      <strong data-bind="text: name"></strong>
      <div data-bind="component: { name: 'like-widget', params: {data: $data}}"></div>
    </li>
  </ul>

组件如下:

ko.components.register('like-widget', {
  viewModel: function(params) {
    // Data: value is either null, 'like', or 'dislike'
    this.data = params.data;

    // Behaviors
    this.like = function() {
      this.data.userRating('like');
    }.bind(this);
    this.dislike = function() {
      this.data.userRating('dislike');
    }.bind(this);
  },
  template: '<div data-bind="with: data"><div class="like-or-dislike" data-bind="visible: !userRating()">\
            <button data-bind="click: $parent.like">Like it</button>\
            <button data-bind="click: $parent.dislike">Dislike it</button>\
        </div>\
        <div class="result" data-bind="visible: userRating">\
            You <strong data-bind="text: userRating"></strong> it\
        </div></div>'
});

这样做可行,但似乎有更简单的方法将组件的 viewModel 设置为 $data。

这是正确的方法还是我遗漏了什么?

您可以在 Product 中定义喜欢和不喜欢的功能 class 并使用模板绑定,这样您就可以将整个 Product 对象绑定到模板。

我已经分叉了你的 plunk 来展示我是如何做到的

http://plnkr.co/edit/fYaBw1Yjsivg6O8x3JgB

<div data-bind="template: { name: 'like-template', data: $data}"></div>

模板看起来像这样

<script type="text/html" id="like-template">
        <div class="like-or-dislike" data-bind="visible: !userRating()">
            <button data-bind="click:like">Like it</button>
            <button data-bind="click:dislike">Dislike it</button>
        </div>
        <div class="result" data-bind="visible: userRating">
            You <strong data-bind="text: userRating"></strong> it
        </div></div>
  </script>

虽然您可以将 $data 作为参数传递,但请注意,您现在已经将组件的设计与视图模型的设计紧密耦合。一种更可重用的方法是将名称和 userRating 作为参数传递,并使用它们为对产品视图模型的结构一无所知的组件构建视图模型。

也就是说,您无需将 $data 作为参数传递给组件即可访问它。相反,您可以在组件绑定到的元素上使用 ko.contextFor,并以这种方式获取 $data。

示例:

ko.components.register('like-widget', {    
    viewModel: {
        createViewModel: function (params, componentInfo) {
            var context = ko.contextFor(componentInfo.element);

            var self = context.$data;

            return ko.utils.extend(context.$data, {
                ratingButtonVisible: ko.computed(function() {
                    return (self.userRating()==null);
                }),

                ratingDescriptionVisible: ko.computed(function() {
                    return !(self.userRating()==null);
                }),                

                like:   function() {                    
                    self.userRating('like');
                },

                dislike:  function() {                    
                    self.userRating('dislike');
                }
            });
        }            
    },
    template: { element: 'like-template' }
});

ko.applyBindings(new MyViewModel());

工作JSFiddle