Durandal观点是AMD模块。 shell是一个特殊的案例视图,也是一个模块。
我的理解是,如果我写了一个模块来返回一个对象实例,那么我会在任何需要它的模块中获得对同一实例的引用;而对于返回构造函数的模块,将调用构造函数以生成私有实例。
我有一个登录视图(惊讶,惊讶)验证用户并显示属性IsAuthenticated
。这是一个淘汰可观察的,并且各种UI绑定到它,以便当login.IsAuthenticated()
返回false时,您获得登录UI,当它返回true时,您将获得任何身份验证的前提条件。
这一切都有效,但只有一次。当我添加了一个注销功能,该功能使服务器上的会话令牌到期并在客户端设置login.IsAuthenticated(false)
时,所有成功响应登录的UI都无法响应注销。
注销功能在shell中实现,因为它的应用范围很广。 shell.js的开头看起来像这样:
define(['plugins/router', 'knockout', 'config', 'viewModels/login'],
function (router, ko, config, login) {
var shell = {
login: login,
check: function () {
alert(login.IsAuthenticated());
},
检查方法是存在的,因为在解决这个问题的过程中,我在shell中放了一个按钮,调用check来告诉我login.IsAuthenticated()
返回什么。实验结果表明,引用登录的每个模块似乎都获得了一个包含输入时值的副本。
我认为这里的问题是误解了RequireJS的行为。
实施这种应用范围状态的正确方法是什么?
答案 0 :(得分:1)
答案是将app状态放在app对象中。
根据路易斯的观察,如果单身人士不工作则出现问题,那么在shell视图模型中声明对视图模型的依赖存在问题。
如果你这样做,那么你最终会得到两份副本。我不知道为什么,但它发生了,而这正是我所看到的所有古怪的基础。
所以,如果你不能这样做那么可以你做什么?
实际上不需要shell引用任何视图模型。
当然,在某些情况下,视图和视图模型可以允许用户操作应用程序状态,例如设置或身份验证。
在这种情况下,信息实际上属于整个应用程序:app对象就是模型。这不仅在逻辑上是正确的,它使问题完全消失。例如,我的登录视图模型现在由可观察的app.IsAuthenticated()
支持,该define(['durandal/app', 'knockout', ...], (function (app, ko, ...) {
app.IsAuthenticated = ko.observable();
var shell = {
app: app,
...
};
return shell;
}
已经在shell的范围内。
现在,shell视图确实需要在绑定阶段之前存在此observable。它还需要一个app对象的名称,该对象是绑定器的范围,因此在shell实现中我设置了它们。
define(['durandal/app'], function (app) {
return {
activeView: ko.computed(function () {
return app.IsAuthenticated() ?
"viewmodels/upload-queue" :
"viewmodels/login";
}, null)
};
});
和鲍勃是你的叔叔!有了这个基础设施,您就可以使用这么薄的包装来保护内容。
查看模型
<div data-bind="compose: activeView"></div>
查看强>
<div class="btn btn-default pull-right"
data-bind="click: app.logout, visible: app.IsAuthenticated">
<i class="icon-signout" title="Log out"></i>
</div>
注意非常简单的占位符标记。回到shell,我们现在可以在标记中使用这些信息了:
app.logout = login.logout;
精明的读者会想知道app如何获得注销方法。实际上这是登录对象的一种方法,它在登录视图模型模块中分配给app,如下所示:
{{1}}