我正在尝试在knockout
内创建自定义组件加载器,但我正在努力使用视图模型。基本上我想远程获取HTML模板和JavaScript视图模型,但在这个例子中我不想使用传统的AMD模块加载器。
我设法让其中一些工作,特别是加载HTML模板,但我无法弄清楚如何加载视图模型。在我开始之前是我的目录结构:
- index.html
- customerLoader.js
- comps
- myCustom.html
- myCustom.js
所以我创建了我的组件加载器。 getConfig
基本上采用组件的名称,并将其转换为viewModel和html模板的路径。
var customLoader = {
getConfig: function(name, callback) {
callback({ template: "comps/" + name + ".html", viewModel: "comps/" + name + ".js" });
},
loadTemplate: function(name, templateConfig, callback) {
console.log("loadTemplate", name, templateConfig);
$.get(templateConfig, function(data) {
callback(data);
});
},
loadViewModel: function(name, templateConfig, callback) {
console.log("loadViewModel", name, templateConfig);
$.getScript(templateConfig, function(data) {
callback(data);
});
}
};
ko.components.loaders.unshift(customLoader);
这成功地发出了加载模板的请求,这带来了一些基本内容。我正在努力的是视图模型。我不确定我的JavaScript文件的目标应该是什么?
我假设我想要返回一个带有一些参数的函数,很可能是一个params
对象。但是,如果我尝试这样做,我会收到错误,告诉我JavaScript无效:
Uncaught SyntaxError:非法返回语句
这是我收到的产生此错误的当前内容:
return function(params) {
console.log("myCustom.js", name, viewModelConfig);
// Add a computed value on
params.bookNum = ko.computed(function() {
switch(this.title()) {
case "A": return 1;
case "B": return 2;
case "C": return 3;
default: return -1;
}
});
//ko.components.defaultLoader.loadViewModel(name, viewModelConstructor, callback);
};
所以最终我不确定如何实现这一点,但我想有3个基本问题可以解释我理解中的差距:
ko.components.defaultLoader.loadViewModel
?customLoader
内loadViewModel()
应该对jQuery回调的结果做什么?我不确定我是否收回了一个JavaScript对象,或者只是一个字符串? 如果需要,我愿意以不同的方式实现这一点(例如,不使用jQuery但以不同的方式获取文件),但我不想使用模块加载器(例如require.js / curl.js)在这个例子中)。
答案 0 :(得分:1)
首先让我们弄清楚发生了什么...
来自docs:
这个(
$.getScript()
)是一个简写的Ajax函数,相当于:$.ajax({ url: url, dataType: "script", success: success });
...
dataType: ...
"script"
:将响应评估为JavaScript并将其作为纯文本返回。
因此,您的代码被提取,评估,然后将作为文本返回,但评估首先失败,因为如果您不在函数内,则无法return
。
那么可以做些什么呢?有几种选择:
将脚本更改为合法脚本
因为在全局代码中使用return
语句是非法的,所以当前代码会失败。但是,您可以创建一个命名函数(或带有函数表达式的变量),然后使用该名称来引用该函数。它看起来像这样:
function myCreateViewModel(param) {
// whatever
}
用法是:
$.getScript(templateConfig, function() {
callback(myCreateViewModel);
});
这里的缺点是,如果您在同一页面中两次浏览该代码路径,您的脚本将覆盖旧的声明。这可能不是问题,但感觉很脏。
不使用 $.getScript()
,使用 $.ajax()
(或 $.get()
) dataType: 'text'
并评估自己。
从代码中删除return
,并使用eval()
进行包装。它将被评估为函数表达式,eval的返回值将是您的函数,您可以将其直接传递给回调函数:
$.get({
url: templateConfig,
dataType: 'text',
success: function(text) {
callback(eval(text));
}
});
这会有效,但它会使用eval()
的皱眉,这会让你面临各种风险。