我最近刚受命创建一个SPA。因此,我创建了一个新项目并选择了SPA,发现它加载了我需要的所有文件,包括这个knockout.js。
我是knockout.js的新手,所以我看了一些视频,我明白了,但是SPA项目对我来说似乎并不算,因为它不是单页应用程序,因为你必须转到一个新的网址来登录、注册、授权、管理帐户等等(你知道了)。
因此,查看索引页的代码,我可以看到homeView的视图模型。看起来是这样的:
function HomeViewModel(app, dataModel) {
var self = this;
self.myHometown = ko.observable("");
Sammy(function () {
this.get('#home', function () {
// Make a call to the protected Web API by passing in a Bearer Authorization Header
$.ajax({
method: 'get',
url: app.dataModel.userInfoUrl,
contentType: "application/json; charset=utf-8",
headers: {
'Authorization': 'Bearer ' + app.dataModel.getAccessToken()
},
success: function (data) {
self.myHometown('Your Hometown is : ' + data.hometown);
}
});
});
this.get('/', function () { this.app.runRoute('get', '#home') });
});
return self;
}
app.addViewModel({
name: "Home",
bindingMemberName: "home",
factory: HomeViewModel
});HTML看起来是这样的:
<!-- ko with: home -->
<!-- removed HTML to make it concise -->
<!-- /ko -->现在,从这个外观来看(如果我错了,请更正我),带有句柄的声明,如果有一个名为home的变量,那么显示它(我假设这就是bindingMembername )。
因此,看到我可以猜测,如果我添加了另一个部分页,并包括它。我可以创建这样的视图模型:
function DrawViewModel(app, dataModel) {
var self = this;
Sammy(function () {
this.get('#draw', function () {
app.home = null;
});
});
return self;
}
app.addViewModel({
name: "Draw",
bindingMemberName: "draw",
factory: DrawViewModel
});因此,从理论上讲,因为这会将app.home设置为null,所以当任何人导航到# not时,就不会显示主部分,类似地,我可以将app.draw = null添加到homeViewModel的sammy路由中,以使homeViewModel隐藏绘制部分。
我的问题是,我创建的viewModels越多,它就会变得越来越复杂。有什么东西我遗漏了吗?有更简单的方法吗?
我的最终目标是将所有页面移动为SPA (包括登录/注册页面)。
提前干杯,/r3plica
发布于 2014-09-02 18:33:50
嗯,经过一番周旋之后,我发现了该怎么做。基本上,我重写了AddView方法并使其看起来如下:
// Other operations
self.addViewModel = function (options) {
var viewItem = new options.factory(self, dataModel),
navigator;
// Add view to AppViewModel.Views enum (for example, app.Views.Home).
self.Views[options.name] = viewItem;
// Add binding member to AppViewModel (for example, app.home);
self[options.bindingMemberName] = ko.computed(function () {
if (self.view() !== viewItem) {
return null;
}
return new options.factory(self, dataModel);
});
if (typeof (options.navigatorFactory) !== "undefined") {
navigator = options.navigatorFactory(self, dataModel);
} else {
navigator = function () {
self.view(viewItem);
};
}
// Add navigation member to AppViewModel (for example, app.NavigateToHome());
self["navigateTo" + options.name] = navigator;
};如果检查当前持有的视图是否与我添加的视图不同,您是否可以看到。如果是,则返回null (这是如何让它隐藏任何未使用的视图)。为了进一步回答我的问题,我需要一种方法,以解决如何直接到登录页面,如果用户没有登录。
在app.viewmodel.js中,我再次添加了一些可观察到的属性:
// UI state
self.user = ko.observable(null);
self.loggedIn = ko.computed(function () {
return self.user() !== null;
});在我的新login.viewmodel.js中,我添加了以下函数:
// Operations
self.login = function () {
self.loggingIn(true);
dataModel.login({
grant_type: "password",
username: self.userName(),
password: self.password()
}).done(function (data) {
if (data.userName && data.access_token) {
app.navigateToLoggedIn(data.userName, data.access_token, self.rememberMe());
} else {
//self.errors.push("An unknown error occurred.");
}
}).fail(function (jqXHR, textStatus, error) {
dataModel.displayError(jqXHR);
}).always(function () {
self.loggingIn(false);
});
};这里的重要部分是app.naviateToLoggedIn方法。它位于app.viewmodel.js中,如下所示:
// UI operations
self.navigateToLoggedIn = function (userName, accessToken, persistent) {
if (accessToken) {
dataModel.setAccessToken(accessToken, persistent)
}
self.user(new UserViewModel(self, userName, dataModel));
self.navigateToHome();
};userViewModel非常简单:
function UserViewModel(app, name, dataModel) {
var self = this;
// Data
self.name = ko.observable(name);
// Operations
self.logOff = function () {
dataModel.logout().done(function () {
app.navigateToLoggedOff();
}).fail(function (jqHXR) {
dataModel.displayError(jqHXR);
});
};
return self;
}最后,为了使初始加载正确,在home.viewmodel.js js文件中,我有以下sammy声明:
Sammy(function () {
this.get('#home', function () {
if (app.loggedIn()) {
app.navigateToHome();
} else {
window.location.hash = "login";
}
});
this.get('/', function () { this.app.runRoute('get', '#home') });
});https://stackoverflow.com/questions/25623332
复制相似问题