从JavaScript文件

时间:2015-09-28 20:55:26

标签: javascript knockout.js

我正在尝试在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个基本问题可以解释我理解中的差距:

  1. 我的“视图模型”JavaScript文件应包含哪些内容?一个功能?一个东西?等...
  2. 我是否需要拨打ko.components.defaultLoader.loadViewModel
  3. 在我的customLoaderloadViewModel()应该对jQuery回调的结果做什么?我不确定我是否收回了一个JavaScript对象,或者只是一个字符串?
  4. 如果需要,我愿意以不同的方式实现这一点(例如,不使用jQuery但以不同的方式获取文件),但我不想使用模块加载器(例如require.js / curl.js)在这个例子中)。

1 个答案:

答案 0 :(得分:1)

首先让我们弄清楚发生了什么...

来自docs

  

这个($.getScript())是一个简写的Ajax函数,相当于:

$.ajax({
  url: url,
  dataType: "script",
  success: success
});

来自jQuery.ajax()

  

...
   dataType: ...
      "script":将响应评估为JavaScript并将其作为纯文本返回。

因此,您的代码被提取,评估,然后将作为文本返回,但评估首先失败,因为如果您不在函数内,则无法return

那么可以做些什么呢?有几种选择:

  1. 使用模块加载程序。
    jQuery不是模块加载器,因此它无法解析获取的代码并从该代码创建值/对象。模块加载器专门为此任务而设计。它将采用以特定模式编写的脚本并将其“评估”为值(通常是具有1个或多个属性的对象)。
  2. 将脚本更改为合法脚本
    因为在全局代码中使用return语句是非法的,所以当前代码会失败。但是,您可以创建一个命名函数(或带有函数表达式的变量),然后使用该名称来引用该函数。它看起来像这样:

    function myCreateViewModel(param) {
      // whatever
    }
    

    用法是:

    $.getScript(templateConfig, function() {
        callback(myCreateViewModel);
    });
    

    这里的缺点是,如果您在同一页面中两次浏览该代码路径,您的脚本将覆盖旧的声明。这可能不是问题,但感觉很脏。

  3. 不使用 $.getScript() ,使用 $.ajax() (或 $.get() dataType: 'text' 并评估自己。
    从代码中删除return,并使用eval()进行包装。它将被评估为函数表达式,eval的返回值将是您的函数,您可以将其直接传递给回调函数:

    $.get({
      url: templateConfig,
      dataType: 'text',
      success: function(text) {
        callback(eval(text));
      }
    });
    

    这会有效,但它会使用eval()的皱眉,这会让你面临各种风险。