【发布时间】:2016-06-10 12:45:46
【问题描述】:
我正在尝试使用 KnockoutJS SPA Yeoman 生成器来构建 SPA 应用程序并使用 ko.mapping 插件。我已经调整了 require.config.js 以包含 ko-mapping。
在独立应用程序中,我可以让映射插件正常工作,但是当我尝试在组件的构造函数中使用它时,绑定在模板 html 中永远不可用。关于我可能做错了什么让映射插件在 KO 组件中播放的任何想法?
var require = {
baseUrl: ".",
paths: {
"bootstrap": "bower_modules/components-bootstrap/js/bootstrap.min",
"crossroads": "bower_modules/crossroads/dist/crossroads.min",
"hasher": "bower_modules/hasher/dist/js/hasher.min",
"jquery": "bower_modules/jquery/dist/jquery",
"knockout": "bower_modules/knockout/dist/knockout",
"komapping": "bower_modules/knockout-mapping/knockout.mapping",
"knockout-projections": "bower_modules/knockout-projections/dist/knockout-projections",
"signals": "bower_modules/js-signals/dist/signals.min",
"text": "bower_modules/requirejs-text/text"
},
shim: {
"bootstrap": { deps: ["jquery"] },
"komapping": { deps: ["knockout"], exports: 'komapping'}
}
};
define(['jquery', 'knockout', './router', 'bootstrap', 'knockout-projections'], function($, ko, router) {
// Components can be packaged as AMD modules, such as the following:
ko.components.register('nav-bar', { require: 'components/nav-bar/nav-bar' });
ko.components.register('home-page', { require: 'components/home-page/home' });
// ... or for template-only components, you can just point to a .html file directly:
ko.components.register('about-page', {
template: { require: 'text!components/about-page/about.html' }
});
ko.components.register('bems', { require: 'components/bems/bems' });
ko.components.register('user-page', { require: 'components/user-page/user' });
ko.components.register('team-page', { require: 'components/team-page/team' });
ko.components.register('exec-page', { require: 'components/exec-page/exec' });
// [Scaffolded component registrations will be inserted here. To retain this feature, don't remove this comment.]
// Start the application
ko.applyBindings({ route: router.currentRoute });
});
define(['knockout', 'text!./bems.html','komapping'], function(ko, templateMarkup, komapping) {
function Bems(params) {
ko.mapping = komapping;
var self = this;
self.response = ko.observable();
if (typeof params[0] != 'undefined') {
// Suppress search while loading
document.getElementById("bems-input").style.visibility = "hidden";
self.bemsId = String(params[0]);
$.ajaxSetup({
cache: false,
"error":function() {
document.getElementById("bems-input").style.visibility = "visible";
window.location = ("#/bems/");
}
});
$.getJSON('/app/skyline/api/bems/' + self.bemsId, function(ajax_response) {
document.getElementById("bems-input").align = "right";
document.getElementById("bems-input").style.visibility = "visible";
document.getElementById("bems-container").style.visibility = "visible";
ko.mapping.fromJS(ajax_response, {}, self.response);
});
}
// Nothing to do without bemsId parameter
}
return { viewModel: Bems, template: templateMarkup };
});
我还测试了以下更改:
self.response = ko.observable();
self.message = ko.observable("It works");
$.getJSON('/app/skyline/api/bems/' + self.bemsId, function(ajax_response) {
self.response = ko.mapping.fromJS(ajax_response);
在上面self.message 正确绑定并且可以在模板中访问。但是self.response 中的映射属性未绑定。
我的工作设置和损坏案例之间的主要区别在于工作示例中我将 ko.mapping 结果设置为整个视图模型变量,其中函数 Bems 是视图模型,这是 vm 下的变量.
我今天又看了一遍,并接近了这个问题。看起来主要问题是触发 AJAX 回调和通过 Yoeman 组件应用程序框架发生的绑定之间的操作顺序。如果我执行以下操作并在主 ViewModel 中延迟 2 秒,它会设法加载视图中第一个绑定属性的绑定内容,但随后会因 TypeError 而死,即使数据确实为属性加载。这会暂停脚本并且不会加载其他属性。
require.js:900 TypeError: Unable to process binding "text: function (){return response().engagement_list()[0].CASE_TITLE }"(…)
function BemsViewModel(params) {
self.response = ko.observable();
$.getJSON('/app/skyline/api/bems/' + self.bemsId(), function(ajax_response) {
$("#bems-input").attr("align","right");
$("#bems-input").attr("style", "visibility: visible")
$("#bems-container").attr("style", "visibility: visible")
var foobar = {};
ko.mapping.fromJS(ajax_response, {}, foobar);
self.response(foobar);
是否有任何最佳实践/模式来确保仅在使用此 KO 组件 SSA 模板加载视图模型的所有位后才发生绑定?任何帮助/想法将不胜感激。我真的不想手动定义整个视图模型...
【问题讨论】: