【问题标题】:Extracting a component from an existing html page to external files从现有的 html 页面中提取组件到外部文件
【发布时间】:2016-04-10 20:43:02
【问题描述】:

我有以下 html/js 现有工作代码,我想将它们提取到他们自己的文件中并使用 require.js 加载它们。

我的目标是将其组件化以便能够在其他地方使用它。

.html

...    
<ul data-bind="foreach: selectedExams">
        <li>
            <select data-bind="options: $parent.availableExams, optionsText: 'examTypeName', optionsValue:'examTypeId', value: examtype"></select>
            <select data-bind="options: exams,  optionsText: 'examName', optionsValue:'examId',value: exam, enable:exams().length"></select>
            <a href="#" data-bind="click: $parent.remove">Remove</a>
        </li>
    </ul>
    <button data-bind="click: add">Add</button>
...

.js

    var self = this;
...
    self.availableExams = [...];

    self.selectedExams = ko.observableArray([new selectedExam(self)]);
    self.add = function () {
        self.selectedExams.push(new selectedExam(self));
    };
    self.remove = function (exam) { self.selectedExams.remove(exam) }
...

起初看起来很简单,但我很困惑,因为视图模型似乎需要完全重写。

因为我想试验一下,看看它是如何工作的,在docs 之后,我创建了一个单独的 .html 文件,其中包含上面显示的所需内容。

还有以下自治的 .js 文件:

function ExamControlViewModel()
{
    var self = this;
    self.availableExams = [...];

    self.selectedExams = ko.observableArray([new selectedExam(self)]);
    self.add = function () {
        self.selectedExams.push(new selectedExam(self));
    };
    self.remove = function (exam) { self.selectedExams.remove(exam) }
}

ko.applyBindings(new ExamControlViewModel());

接下来,我从原始 html/js 文件中删除了代码,并将以下内容添加到 js 文件中:

ko.components.register('exam-control', {
    viewModel: { require: 'exam-control-viewmodel' },
    template: { require: 'text!exam-control-view.html' }
})

它在运行时失败并出现以下错误:

“文本”的脚本错误,需要:text!exam-control-view.html_unnormalized2 http://requirejs.org/docs/errors.html#scripterror

显然我没有抓住重点,这不可能那么简单......可能吗?

任何指导表示赞赏。

编辑 1:

我遵循@JotaBe 的优秀指导,最终得到以下结果:

.js 文件

define([],function() {
    function ExamControlViewModel()
    {
        var self = this;
        self.availableExams = [...];

        self.selectedExams = ko.observableArray([new selectedExam(self)]);
        self.add = function () {
            self.selectedExams.push(new selectedExam(self));
        };
        self.remove = function (exam) { self.selectedExams.remove(exam) }
    }
    return ExamControlViewModel;
});

html 文件: => 开头

...
<script type='text/javascript' src='Scripts/knockout-3.4.0.js'></script>
<script type='text/javascript' src='Scripts/knockout.validation.js'></script>
<script type='text/javascript' src='Scripts/require.js'></script>
<script type='text/javascript' src='Scripts/text.js'></script>
...

=>组件代码被替换为(提问的时候忘了说)

<exam-control></exam-control>

现在在运行时,出现以下错误:

不匹配的匿名 define() 模块

随着我的进步,我会再次更新这个帖子。

【问题讨论】:

    标签: knockout.js requirejs components


    【解决方案1】:

    你必须做这些事情:

    1. 按照 AMD 模式导出模块构造函数
    2. 包含require.js 文本插件,以便通过require 加载模板
    3. 配置 require.js 以便它可以找到您的模板和脚本
    4. 注册组件

    1。导出视图模型构造函数

    导出构造函数的 AMD 模式如下所示:

    define([/*dependencies*/],function() {
      // define the constructor you want to export
      function ExamControlViewModel() { ... }
      // export it
      return ExamControlViewModel;
    });
    

    这必须是您的exam-control-viewmodel.js 文件的唯一内容。不需要applyBindings:knout 会复制模板内容并在脚本和模板都加载时应用绑定。

    我想你已经在全球范围内加载了knockout。如果您这样做了,请按照说明保留定义。但是,如果您使用 require.js 加载 ko 和相关内容(如插件),则应将其作为依赖项包含在文件中:

    define(['ko'],function(ko) {
    

    当然,您需要正确的配置路径才能将淘汰赛加载为ko。如果没有,您必须指定整个文件名(和路径)。

    2。包含 require.js 文本 lugin

    require.jstext 插件可用here,在这里你可以看到related documentation。您可以通过复制它或使用任何可用的包格式来安装它,例如 Nugetnpm

    3。配置require.js

    您必须配置 require 以便它可以找到文件,如 explained here。一定要特别注意baseUrl

    4。注册组件

    您已经完成了组件注册是正确的。特别是'text!exam-control-view.html' 指示require.js 使用text 插件加载模板。 .js 文件必须具有指定的名称。

    由于require.js 和插件的工作方式,正如您所做的那样,必须包含.html 扩展名,并且必须删除.js

    如果您指定了正确的配置,将从指定的baseUrl 读取文件。如果没有,您将不得不对其进行修改。如果它们没有正确加载,您可以使用浏览器的控制台来查找问题所在。

    当然是require.js,并且在使用组件之前必须加载相关配置。

    【讨论】:

    • 优秀的指导!我已经更新了问题,我想我在导出 viewmodel 构造函数时遇到了问题。
    • @omatrot 您的问题太长了,无法阅读。现在你发现了一个新问题,而不是提出一个新问题,你让你的问题变得更长。您只应修改问题以包含新的相关信息或改进措辞。但是,请不要制作这种版本。您的新问题可能是已经回答的问题:stackoverflow.com/questions/15371918/… 查看浏览器的控制台可以帮助您确定问题所在。
    • @omatrot 您的构造函数 AMD 模块是正确的。请尝试在不包含 ko 的情况下同时要求您的脚本和模板,即在仅包含 require 的简单 .html 页面中直接使用 require(['',''], function() {})。然后一一包含所有脚本。你是如何设置 require.js 的?我看不到你在哪里做的。
    • require.js 是通过 Nuget 安装的
    • 不,我不是指您如何安装它,而是您如何指定配置(baseUrl 等)。你是怎么配置的?
    【解决方案2】:

    您应该将text plugin 包含在RequireJS 中。 Here我已经写了比较详细的回答了。

    【讨论】:

      猜你喜欢
      • 2013-10-29
      • 2013-08-04
      • 2015-03-28
      • 1970-01-01
      • 2016-03-28
      • 1970-01-01
      • 2012-01-06
      • 1970-01-01
      • 2022-11-02
      相关资源
      最近更新 更多