我正在为我的骨干应用程序进行登录,遇到了一个问题,我不确定如何在不调用服务器的情况下解决问题。这在我的团队中引发了一场讨论,关于其他人在骨干中处理这种事情的方式,因为我们认为我们将在前进中遇到类似的事情。
今天是星期五,我可能只是脑死亡,但这是…
我们有一个用户模型。View的login方法创建一个新的用户模型,并调用它的login方法,传入用户的凭据和一个回调函数,该回调函数有一个包含用户信息的对象。
下面是View的登录方法:
login: function(event){
event.preventDefault();
var user = new App.User;
user.login($('#username').val(), $('#password').val(),
(function(msg) {
// success callback
if (msg.loggedIn) {
console.log("Authenticate successful: " + JSON.stringify(msg));
var data = { user : msg, bob : "bob", trigger:true };
console.log("Prepared data: " + JSON.stringify(data));
App.router.navigate('home',data);
} else {
console.log("Authenticate unsuccessful: " + JSON.stringify(msg));
}
}).bind(this),
function(msg) {
// failure callback
console.log("Authenticate communication failure: " + JSON.stringify(msg));
alert("Communication fail!");
App.router.navigate('login',{trigger:true});
});
}
我们试图弄清楚的是如何最好地使这个模型数据可用于另一个路由(home),以便我们可以在视图中使用它。
我有这个路由器:
routes: {
'': 'home',
'home': 'home',
'login': 'login'
},
home: function(data){
console.log(data);
}
一旦我们登录了用户,我们需要更新路由并访问该用户的数据,但不希望必须返回到服务器来获取它。
我很担心,因为我们正在构建一种"向导",用户可能需要通过一些步骤向前和向后移动,我不想每次他们在应用程序中导航时都要访问服务器,但看起来我们要么需要将内容保存到全局变量中(不想这样做),要么每次都要返回服务器。我相信其他人也遇到过类似的问题。只是想找点真知灼见。
谢谢!
"看起来我们要么需要将内容保存到全局变量中(不想这样做)"
说明一个显而易见的事实:您将需要保存状态。您可以选择将状态传输到服务器并返回,或者在客户端保留状态。由于您已经确定不希望通过服务器传递状态,因此您只能在客户端上的不同页面(路由)之间保留状态。
这就是全局变量的作用。我知道这听起来很讨厌,但这也是单页应用程序带来的主要好处之一。有状态性。并且该状态将始终由某个全局对象保持。
管理状态的方法有好有坏。有一个全局变量叫data
,你不断地赋值和重新赋值显然是最糟糕的方法。您应该找出一个对您的需求有意义的模式。
如果我正确理解了你的代码示例,你想要存储的是关于当前用户的信息。似乎您已经有了一个全局变量App
。我突然想到,保留一些session
信息是个好主意:
login: function(data){
doLogin({
success: function(userData) {
App.session.currentUser = userData;
App.router.navigate('home', { trigger:true });
}
});
},
home: function(data){
if(!App.session || !App.session.currentUser) {
App.router.navigate('login', { trigger:true });
return;
}
var user = App.session.currentUser;
//do something with user
}
国家不一定是邪恶的。糟糕的是依赖于整个应用程序的全局状态,这很容易导致不可测试的意大利面条式代码。但是,如果你尽可能地将状态依赖解决为链中的"高层"(例如在Router中),并使用构造函数和方法参数向下传递值,你仍然可以在其余的代码库中保持可测试性和无副作用。
对不起,我没有银弹给你。有一些图书馆,骨干。StateManager,它可以帮助管理状态,转换等,但本质上它们不会做任何你不能自己做的事情。使用localStorage!
修改代码如下:
// success callback
if (msg.loggedIn) {
console.log("Authenticate successful: " + JSON.stringify(msg));
var data = { user : msg, bob : "bob", trigger:true };
var dataString = JSON.stringify(data);
console.log("Prepared data: " + dataString;
window.localStorage.setItem("userdata",dataString);
App.router.navigate('home',data);
现在,当您需要检查用户是否已登录时,请执行以下操作:
try {
var userData = window.localStorage.getItem ("userdata");
} catch (e) {
// Do something
}
try-catch是必要的,以确保您的代码在身份验证从未成功时不会出错。
现在回复太晚了,但是有另一种更好的方法来做到这一点,这取决于你正在使用的路由器引擎,并且没有局部变量。我将尝试给出一个使用backbone的通用示例,它适用于所有。
一般来说,你的路由器会在一个地方的事情被处理。假设它的主干让路由定义如下:
var router = Backbone.Router.extend({
routingData: {}, // this will have the routing data
routes: {
'': 'home',
'home': 'home',
'login': 'login'
},
navigate: function(url, data) {
this.routingData["data"] = data; // whenever navigation is done, this will be reset
//This is the routing code whichever the f/w may be.
Backbone.Router.prototype.navigate(route, { trigger: true });
},
home: function(data) {
var params = this.routingData["data"]; //retreiving the routing params
console.log(params);
}
})
现在如果你想传递数据,你可以做
router.navigate(<URL>,<SOME DATA>)