在不进入服务器的情况下在路由之间保留数据?

时间:2013-01-04 20:25:22

标签: backbone.js

我正在为我的主干应用程序登录并遇到一个问题我不知道如何在不调用服务器的情况下解决。这让我的团队讨论了其他人在骨干中处理这种事情的方式,因为我们认为我们将会遇到类似的事情。

这是星期五,我可能只是脑死了,但是这里......

我们有一个用户模型。 View的登录方法创建一个新的用户Model并调用它的登录方法传递用户的凭据和一个回调函数,该函数有一个包含用户信息的对象。

以下是我们的视图的登录方法:

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}); 
        });
}

我们想要弄清楚的是如何最好地将此模型数据提供给另一条路线(家庭),以便我们可以在视图中使用它。

所以我有这个路由器:

routes: {
'': 'home',
'home': 'home',
'login': 'login'
},
home: function(data){
   console.log(data);
}

一旦我们记录了用户,我们需要更新路由并访问该用户数据,但不想返回服务器以获取它。

我很担心,因为我们正在构建一种“向导”,用户可能需要前进和后退一些步骤,我不希望每次浏览应用程序时都要点击服务器,但是看起来我们要么需要将内容保存到全局变量(不想这样做),要么每次都要返回服务器。我相信其他人不得不处理类似的问题。只是寻找一些见解。

谢谢!

3 个答案:

答案 0 :(得分:5)

  

“看起来我们要么需要将内容保存到全局变量中(不想这样做)”

说明显而易见的:你需要保持状态。您可以选择将状态转移到服务器并返回,或者在客户端上保持状态。由于您已经确定不希望通过服务器传递状态,因此您可以在客户端上的不同页面(路由)之间保留状态。

这就是全局变量的用途。我知道,它听起来像是 icky ,但它也是单页面应用程序带来的主要好处之一。有状态。而且这种状态总是由一些全球性的对象来控制。

管理国家的方式越来越好。拥有一个名为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
}

国家不一定是邪恶的。什么是邪恶取决于整个应用程序的全局状态,这很容易导致不可测试的意大利面条代码。但是如果你将状态依赖关系尽可能地解析为链中的“up up”(例如在路由器中),并使用构造函数和方法参数传递值,那么你仍然可以在其余部分中保持可测试性和副作用。代码库。

很抱歉,我没有银弹。其中有一些库Backbone.StateManager,它们可以帮助管理状态,转换等,但基本上它们不做任何你不能做的事情。

答案 1 :(得分:1)

使用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是必要的,以确保您的代码不会被禁止。

答案 2 :(得分:0)

回复已太晚了,但根据您使用的路由器引擎并且没有本地变量,还有另一种更好的方法可以做到这一点。 我会试着用一个适用于所有人的骨干的一般例子。

通常,您的路由器将位于正在处理事物的位置。假设它的骨干允许路由定义如下。

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>)