在路由之间持久化数据,而不需要访问服务器



我正在为我的骨干应用程序进行登录,遇到了一个问题,我不确定如何在不调用服务器的情况下解决问题。这在我的团队中引发了一场讨论,关于其他人在骨干中处理这种事情的方式,因为我们认为我们将在前进中遇到类似的事情。

今天是星期五,我可能只是脑死亡,但这是…

我们有一个用户模型。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>)

相关内容

最新更新