为Knockout组件加载外部ViewModel和模板

时间:2017-08-12 20:21:35

标签: ajax knockout.js requirejs

我正在尝试使用require.js将模板加载到用于挖空组件的viewmodel,但到目前为止还没有成功。

index.html(查看)

<!doctype html>
<head>
    <link href="assets/css/bootstrap.min.css" rel="stylesheet" />
    <script data-main="assets/js/app" src="assets/js/vendor/require.js"></script>
</head>
<body>
    <table_n></table_n>
</body>

menu.html(模板)

<table class="table table- bordered table-hover">
    <thead>
        <tr>
            <th align=center width=60 style="display: none">Código</th>
            <th>Título</th>
            <th>Descrição</th>
            <th>Ordem</th>
            <th>Imagem url</th>
        </tr>
    </thead>
    <tbody data-bind="foreach: {data: ListaUsuarios()}">
        <tr>
            <td style="display: none" data-bind="text: id"></td>
            <td data-bind="text: titulo"></td>
            <td data-bind="text: descricao"></td>
            <td data-bind="text: ordem"></td>
            <td data-bind="text: caminho_imagem"></td>
        </tr>
    </tbody>
</table>

menu.js(ViewModel)

define(['knockout', 'knockoutMapping'], function (ko, komap) {
    debugger;
    var self = this;
    debugger;
    self.filter = ko.observable('');
    self.ListaUsuarios = ko.observableArray();

    $.ajax({
        type: "GET",
        url: "http://192.168.15.3/api/menus",
        contentType: "application/javascript",
        dataType: "json",
        success: function (result) {
            var a = JSON.stringify(result);
            var observableData = komap.fromJS(result);
            var array = observableData();
            self.ListaUsuarios(array);
        }
     });
});

App.js(初始化淘汰赛参数)

(function (undefined) {
    'use strict';
    requirejs.config({
        baseUrl: './', // Raiz
        urlArgs: function (id, url) {
            return (url.indexOf('?') === -1 ? '?' : '&') + 'v=23';
        }, // Debug Cache
        deps: ['assets/js/base'],
        map: {
            '*': {
                'jQuery': 'jquery'
            }
        },
        paths: {
            // Módulos
            'jquery': 'assets/js/vendor/jquery-3.1.1',
            // Library jQuery
            'knockout': 'assets/js/vendor/knockout-3.4.2',
            'knockoutMapping': 'assets/js/vendor/knockout.mapping-latest',
            // Config
            'start': 'assets/js/start'
        },
        shim: {
            'knockoutMapping': {
                deps: ['knockout']
            }
        },
        waitSeconds: 15
    });
    // Chamando módulo principal para iniciar a aplicação
    require(['jquery'], function ($) {
        require(['start']);
    });
    requirejs.onError = function (err) {
        console.log(err.requireType);
        console.log('modules: ' + err.requireModules);
        throw err;
    };
}());

base.js(使用jQuery作为RequireJS中命名的模块)

(function () {
    define(['jquery'], function () {
        (function ($) {
            console.info('Verificando Global jQuery...');
            if (typeof window === 'object' && typeof window.document === 'object') {
                if (!!window && !(!!window.$)) {
                    window.jQuery = window.$ = jQuery;
                }
                console.log([$, jQuery]);
            }
            var version = $().jquery;
            if (typeof define === "function" && define.amd && define.amd.jQuery) {
                console.info('jQuery: ' + version + ' $.fn.jquery: ' + $.fn.jquery);
                return window.jQuery;
            }
        }(jQuery));
    });
}());

start.js(最后初始化组件)

define(['knockout', 'knockoutMapping'], function (ko, komap) {
    debugger;
    ko.components.register('table_n', {
        viewModel: { require: 'assets/js/component/viewmodel/menu' },
        template: { require: 'text!assets/js/component/templates/menu.html' }
    });

    ko.applyBindings();
});

我在浏览器上调试时遇到了很多错误

Verificando Global jQuery...
require.js:5 Array(2)
require.js:5 jQuery: 3.1.1 $.fn.jquery: 3.1.1
text.js Failed to load resource: the server responded with a status of 404 (Not Found)
app.js:36 scripterror
app.js:37 modules: text
app.js:38 Uncaught Error: Script error for "text", needed by: text!assets/js/component/templates/menu.html_unnormalized2
http://requirejs.org/docs/errors.html#scripterror
    at makeError (require.js:5)
    at HTMLScriptElement.onScriptError (require.js:5)
makeError @ require.js:5
onScriptError @ require.js:5
app.js:36 require
app.js:37 modules: null
app.js:38 Uncaught TypeError: Cannot read property 'createViewModel' of undefined
    at c (knockout-3.4.2.js?v=23:80)
    at Object.loadViewModel (knockout-3.4.2.js?v=23:82)
    at Object.e [as Nb] (knockout-3.4.2.js?v=23:78)
    at knockout-3.4.2.js?v=23:79
    at Object.execCb (require.js:5)
    at b.check (require.js:5)
    at b.<anonymous> (require.js:5)
    at require.js:5
    at require.js:5
    at each (require.js:5)
c @ knockout-3.4.2.js?v=23:80
loadViewModel @ knockout-3.4.2.js?v=23:82
e @ knockout-3.4.2.js?v=23:78
(anonymous) @ knockout-3.4.2.js?v=23:79
execCb @ require.js:5
check @ require.js:5
(anonymous) @ require.js:5
(anonymous) @ require.js:5
(anonymous) @ require.js:5
each @ require.js:5
emit @ require.js:5
check @ require.js:5
enable @ require.js:5
init @ require.js:5
h @ require.js:5
completeLoad @ require.js:5
onScriptLoad @ require.js:5
app.js:36 timeout
app.js:37 modules: text!assets/js/component/templates/menu.html_unnormalized2
app.js:38 Uncaught Error: Load timeout for modules: text!assets/js/component/templates/menu.html_unnormalized2
http://requirejs.org/docs/errors.html#timeout
    at makeError (require.js:5)
    at l (require.js:5)
    at require.js:5
makeError @ require.js:5
l @ require.js:5
(anonymous) @ require.js:5
(unknown) XHR Loaded (menus - 200 OK - 971.9319999858271ms - 525B)

1 个答案:

答案 0 :(得分:2)

在看到一些关于使用require的例子之后,我理解我做错了什么:

index.html文件,menu.html(模板)是正确的,但在文件menu.js(ViewModel)中,我更改了第一行以包含 Jquery库,如下所示:

Define (['jquery', 'knockout', 'knockoutMapping'], function ($, ko, komap) {

在文件的最后:

Self.User List (array);

我添加了Knockout Applybinds:

Ko.applyBindings ();

之前它在start.js文件中,但是当我用ajax(异步)查询WebApi时,它在ajax完成查询之前被激活,导致错误。

在app.js文件中,我在路径会话中添加了一个名为text.js的lib,这个libreary可以在download here中找到 该库需要加载模板,因为默认情况下需要加载.js文件。

并且还添加了viewmodel menu.js

的路径

因此文件的修改部分是

  'text': 'assets/js/vendor/text',
  'menu': 'assets/js/component/viewmodel/menu',

请记住,这是在&knockoutMapping&#39;之后添加到会话路径中的。在开始之前#。

base.js文件也没有改变。

并且在文件中删除了start.js,正如我之前所说的,applybindings并修改了第一行。现在,我通过&#39; define&#39;中引用的变量调用Viewmodel和模板。文件看起来像这样:

<强> Start.js:

define(['knockout', 'knockoutMapping', 'menu', 'text!assets/js/component/templates/menu.html'], function (ko, komap, menu, menuhtml) {
    ko.components.register('table_n', {
        viewModel: menu,
        template: menuhtml
    });
});

并且表格已正确加载。