从JavaScript文件加载自定义组件ViewModel
我试图在从JavaScript文件加载自定义组件ViewModel,javascript,knockout.js,Javascript,Knockout.js,我试图在knockout中创建一个自定义组件加载器,但我在视图模型方面遇到了困难。基本上,我想远程获取HTML模板和JavaScript视图模型,但在本例中,我不想使用传统的AMD模块加载器 我已经设法实现了一些功能,特别是加载HTML模板,但我不知道如何加载视图模型。在开始之前,这里是我的目录结构: --index.html --customerLoader.js --comps -- myCustom.html -- myCustom.js 所以我创建了我的组件加载器ge
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无效:
未捕获的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);
};
因此,最终我不确定如何实现这一点,但我想有三个基本问题可以解释我理解上的差距:
ko.components.defaultLoader.loadViewModel
customLoader
中,loadViewModel()
应该如何处理jQuery回调的结果?我不确定我是得到一个JavaScript对象,还是一个字符串李>
如果需要的话,我愿意以不同的方式实现这一点(例如,不使用jQuery,而是以不同的方式获取文件),但我不想使用模块加载器(例如,在本例中使用require.js/curl.js)。首先让我们看看发生了什么 从: 这(
$.getScript()
)是一个速记Ajax函数,相当于:
$.ajax({
url: url,
dataType: "script",
success: success
});
和来自:
…数据类型:…
“script”
:将响应评估为JavaScript并以纯文本形式返回
因此,您的代码会被提取、求值,然后会作为文本返回,但求值首先会失败,因为如果您不在函数中,则无法返回
那么我们能做些什么呢?有几种选择:
jQuery不是模块加载器,因此它不具备解析获取的代码并从代码中创建值/对象的能力。模块加载器是专门为此任务设计的。它将采用以特定模式编写的脚本,并将其“评估”为值(通常是具有1个或多个属性的对象)
因为在全局代码中使用
return
语句是非法的,所以当前代码失败。但是,您可以创建一个命名函数(或带有函数表达式的变量),然后使用该名称引用该函数。它可能是这样的:
function myCreateViewModel(param) {
// whatever
}
其用法是:
$.getScript(templateConfig, function() {
callback(myCreateViewModel);
});
这里的缺点是,如果在同一页面中两次遍历该代码路径,脚本将覆盖旧的声明。这可能永远不会是个问题,但感觉很脏$.getScript()
,使用$.ajax()
(或$.get()
)和数据类型:“文本”
并评估自己。从代码中删除
return
,并用eval()将其包装起来。它将作为函数表达式进行计算,eval的返回值将是您的函数,您可以将其直接传递给回调:
$.get({
url: templateConfig,
dataType: 'text',
success: function(text) {
callback(eval(text));
}
});
这将起作用,但它将使用皱眉的eval()
,这将使您面临各种风险
您的脚本不应以
返回开头
。它应该是可以独立执行的代码。感谢您的回答@Amit,这很有意义。我假设典型的模块加载器在加载脚本时必须使用eval()
,如果这是获取后执行某些内容的唯一方法?可能实际上使用新函数(…)
,但差别不大。他们会尽可能安全地使用经过测试的代码。是的,我知道eval的问题,所以在决定时会考虑到这一点。一旦我证明其中一种方法有效,我就会接受你的答案。非常感谢。