我试图使用RequireJS简化KnockoutJS组件的开发。问题是,它说我多次将绑定应用于同一个元素。
需要-config.js
var require = {
baseUrl: ".",
paths: {
"bootstrap": "bower_components/bootstrap/dist/js/bootstrap.min",
"jquery": "bower_components/jquery/dist/jquery.min",
"knockout": "bower_components/knockout/dist/knockout",
"text": "bower_components/text/text"
},
shim:{
"bootstrap": {deps: ["jquery"]}
}
}
main.js
define(["jquery", "knockout", "bootstrap"], function($, ko){
ko.components.register("sel-text", { require: "components/selecttextarea/selecttextarea" });
ko.applyBindings({});
});
selecttextarea.js - (我创建的组件)
define(["knockout", "text!./selecttextarea.html"], function(ko, template){
function SelTextareaViewModel(params){
var self = this;
self.items = ko.observableArray(params.items);
self.caption = ko.observable();
}
return{ viewModel: SelTextareaViewModel, template: template};
});
的index.html
<div class="row" id="asd">
<pre data-bind="text: ko.toJSON($root.selectItems)"></pre>
<sel-text params="items: $root.selectItems"></sel-text>
</div>
...
<script>
require(['js/page1']);
</script>
page1.js
require(["jquery", "knockout"], function($, ko){
var data = [{"val": 0, "text": "Hello"}, {"val": 1, "text": "Bloody"}, {"val": 2, "text": "World"}];
function SimpleViewModel(d){
var self = this;
self.selectItems = ko.observableArray(d);
}
ko.applyBindings(new SimpleViewModel(data), $('#asd')[0]);
});
如果我删除<pre>
标记,则表示不会显示错误,就像它尝试将绑定应用于$('#asd')[0]
中的每个元素一样。
我感到困惑,有什么建议吗?
从评论中可以看出,我的main.js中没有applyBindings。如果您查看Steve Sanderson's Knockout Triage repo
,这将适用于单页面应用程序我的工作原理是从applyBindings
移除main.js
,然后在page1.js
:require(["jquery", "knockout", "js/main"], function($, ko)
中要求它们。
理想情况下,这些组件将在全球范围内注册,我甚至不必在页面级别考虑它们,但是嘿嘿。我确实有一个工作示例,我昨天在工作中做了(但我忘了抓一份我的代码)并且工作正常。
答案 0 :(得分:2)
如果您要对一组淘汰组件进行标准化,我建议在模块内注册组件。在下面的示例中,代码使用special 'exports' dependency来定义模块的返回值。这减少了在模块末尾有 return 语句的需要。
define([
'knockout',
'exports',
'text!/.select-text.html'
], function (ko, selectArea, template) {
function SelectArea(params) { ... }
selectArea.viewModel = SelectArea;
selectArea.template = template;
ko.components.register('select-area', selectArea);
});
在模块内部注册组件的好处是,所有内容都是独立的,并且可以记录。然后,如果您有许多组件,则可以创建一个简单的 all.js 模块以包含所有组件定义。 e.g。
define([
'components/selectArea',
'components/selectMultiple',
....
], function () { });
然后只需在 require()调用中包含 all.js ,或者调用 ko的 define()块.applyBindings(),并且在调用ko.applyBindings()之前应该注册所有组件。
require([
'knockout',
...
'components/all'
], function (ko, ...) {
ko.applyBindings(...);
}
如果您有某些特定于页面的组件,则可能需要更改此模式。还有一点需要注意,尽量不要让淘汰组件AMD模块有任何副作用。它应该只定义视图模型和模板。
答案 1 :(得分:0)
From the comments it was made clear to not applyBindings in my main.js. This would work in single page application if you look at Steve Sanderson's Knockout Triage repo
How I got it working was to remove the applyBindings
from main.js
but then require them in page1.j
s: require(["jquery", "knockout", "js/main"], function($, ko)
.
Ideally the components would be registered globally and I wouldn't even have to consider them on a page level but hey-ho. I do have a working example I did at work yesterday (but I forgot to grab a copy of my code) and had it working fine.