为组件设置 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
我刚刚开始了解 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