为 Knockout 组件加载外部 ViewModel 和模板
Load external ViewModel and template for Knockout component
我正在尝试使用 require.js 将模板加载到视图模型中,但目前还没有成功。
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)
在看到一些使用 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 的库,这个库可以在 download here 中找到
此库是加载模板所必需的,因为默认情况下需要加载 .js 文件。
并且还添加了视图模型的路径menu.js
文件的修改部分因此
'text': 'assets/js/vendor/text',
'menu': 'assets/js/component/viewmodel/menu',
请记住,这将添加到 'knockoutMapping' 之后和 'start' 之前的会话路径中。
base.js 文件也没有改变。
并且在文件中 start.js 被删除了,正如我之前所说的,applybindings 并修改了第一行。现在我通过 'define' 中引用的变量调用 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
});
});
这样 table 就被正确加载了。
我正在尝试使用 require.js 将模板加载到视图模型中,但目前还没有成功。
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)
在看到一些使用 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 的库,这个库可以在 download here 中找到 此库是加载模板所必需的,因为默认情况下需要加载 .js 文件。
并且还添加了视图模型的路径menu.js
文件的修改部分因此
'text': 'assets/js/vendor/text',
'menu': 'assets/js/component/viewmodel/menu',
请记住,这将添加到 'knockoutMapping' 之后和 'start' 之前的会话路径中。
base.js 文件也没有改变。
并且在文件中 start.js 被删除了,正如我之前所说的,applybindings 并修改了第一行。现在我通过 'define' 中引用的变量调用 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
});
});
这样 table 就被正确加载了。