我目前正在开发一个测试网络应用来测试Knockout的组件功能。我使用RequireJS来加载组件。虽然我能够这样做,但我被困在一些地区,有些地方,我不确定我做的是不是正确的事。
该应用程序包含一个带标题的页面,左侧栏和右侧剩余空间的内容区域。这3个都注册为组件。左侧栏用作导航,并具有无序列表,其中列表项通过执行AJAX调用来填充。单击列表项时,右侧的内容应显示与单击的列表项对应的组件/视图。
有了这些,这是我的问题:
我只能在实际组件中加载左侧栏的项目。这个可以吗?我的意思是,当左侧栏组件加载时,它会进行AJAX调用,然后在其视图模型上加载数据。我这样做是因为这是我能想到的唯一将数据加载到视图模型的东西。实际上,我更倾向于在应用程序启动时加载数据,然后在侧栏加载时将数据放入其中。所以我的问题是:我做的方法是否正常,是否可以做我喜欢的方法?如果是这样,怎么样?
我不知道如何正确地传达侧栏中的点击以显示右侧的内容。我怎么能以最小的依赖关系来做这件事,或者我该怎么做呢?
具有视图模型的父组件是否可以在其模板中具有子组件,但该子组件是否可以从父视图模型获取其数据?如果是的话,该怎么做?
这些问题让我几天都在阅读,但仍无法让它工作或仍然感到困惑。如果您只对单个项目有答案,请随时发布。希望所有人都能得到答案。
编辑(源代码)
标题:
模板
<div>
</div>
VM
define(["text!./admin-main-header.html"], function(template) {
function AdminMainHeaderViewModel() {
}
return { viewModel: AdminMainHeaderViewModel, template: template };
});
侧栏:
模板
<div class="vmsc" data-bind="with: adminModules, vertMenu: adminModules">
<ul data-bind="foreach: modules">
<li class="has-sub"><a href="javascript:void(0);"><span data-bind="text: name"></span></a>
<ul data-bind="foreach: $data.submodules">
<li><a href="javascript:void(0);"><span data-bind="text: name"></span></a></li>
</ul>
</li>
</ul>
</div>
VM
define(["jquery", "knockout", "ko-mapping",
"jquery-vertmenusc", "text!./vert-menu.html"], function($, ko, komap, vmsc, template) {
ko.mapping = komap;
function VertMenuScViewModel() {
var self = this;
self.adminModules = ko.observable();
$.get("http://localhost:8080/_mock_data/admin-modules.txt", function(data) {
self.adminModules(ko.mapping.fromJSON(data));
});
}
return { viewModel: VertMenuScViewModel, template: template };
});
内容:
模板
<div>
</div>
VM
define(["text!./admin-main-content.html"], function(template) {
function AdminMainContentViewModel() {
}
return { viewModel: AdminMainContentViewModel, template: template };
});
主要HTML:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Sample</title>
<!-- Scripts -->
<script src="js/require.min.2.1.20.js" data-main="js/app/require.config.js"></script>
</head>
<body>
<div>
<admin-main-header></admin-main-header>
<div>
<admin-main-nav></admin-main-nav>
<admin-main-content></admin-main-content>
</div>
</div>
</body>
</html>
我的内容中还没有代码,因为我不知道应该如何传递数据。我希望这些额外信息有所帮助。感谢。
答案 0 :(得分:0)
我认为最能帮助您的功能是using params in the components。我开始使用您的示例代码,但它太复杂,无法做出简单的工作示例。但您的父HTML可能如下所示:
<div>
<admin-main-nav params='lastClicked:chosen'></admin-main-nav>
<admin-main-content params='toDisplay:chosen'></admin-main-content>
</div>
其中chosen
是主视图模型中的一个observable。您的nav viewmodel构造函数可能会以
function VertMenuScViewModel(params) {
var self = this;
self.adminModules = ko.observable();
self.lastClicked = params.lastClicked;
所以现在导航视图模型的lastClicked
成员与来自父视图的chosen
具有相同的可观察性。这是您可以将observable分享到组件的方式。例如,您可以将nav组件写入其中,并从中读取内容组件(以设置其内容)。他们都不知道对方,他们只是知道他们已被赋予可观察性以用于某个目的。
这也是您在主视图模型中加载数据并将其传递给导航组件的方法。