[英]How to navigate, with history, in MVC 5 SPA template?
我在VS2013 SPA MVC-5
模板中的导航中苦苦挣扎。 我做了两个假设(因为我找不到很好的参考),但似乎我错了,或者工作不正常:
它认为导航基于典型的spa # url encoding
,例如,直接导航到users account management page
应该可以使用: http://localhost:18759/#/manage
我还认为,在浏览网站(单页)时,我认为这些# url's
由模板中包含的默认knockout.js
文件形成的。 结合先前的假设,这将导致适当的历史积累。
http://localhost:18759/#/manage
似乎无法导航到manage
页面(其他# url's
也不起作用)。
我注意到一些可用的框架( navrouter
和sammy.js
)可用,但据我所知,要实现它们需要花费很多精力,尤其是如果模板中已经存在它们。
至于为什么我做这些假设的原因,有一篇文章在这里 ,这表明这是地方由于这一部分:
// app.viewmodel.js - there is a method called "addViewModel()
if (typeof (options.navigatorFactory) !== "undefined") {
navigator = options.navigatorFactory(self, dataModel);
} else {
//suggests "#"-hash navigation
navigator = function () {
window.location.hash = options.bindingMemberName;
};
}
但是在我自己的app.viewmodel.js
这些行根本没有引用哈希:
if (typeof (options.navigatorFactory) !== "undefined") {
navigator = options.navigatorFactory(self, dataModel);
} else {
navigator = function () {
self.errors.removeAll();
self.view(viewItem);
};
}
这里在app.viewmodel.js
有对哈希的引用,但这似乎无法处理导航:
// Private operations
function cleanUpLocation() {
window.location.hash = "";
if (typeof (history.pushState) !== "undefined") {
history.pushState("", document.title, location.pathname);
}
}
function getFragment() {
if (window.location.hash.indexOf("#") === 0) {
return parseQueryString(window.location.hash.substr(1));
} else {
return {};
}
}
我的导航代码如下所示:
<ul class="nav navbar-nav navbar-right">
<li data-bind="with: user"><a href="#" data-bind="click: manage">manage</a></li>
</ul>
导航工厂非常默认,例如:
app.addViewModel({
name: "Manage",
bindingMemberName: "manage",
factory: ManageViewModel,
navigatorFactory: function (app) {
return function (externalAccessToken, externalError) {
app.errors.removeAll();
app.view(app.Views.Manage);
if (typeof (externalAccessToken) !== "undefined" ||
typeof (externalError) !== "undefined") {
app.manage().addExternalLogin(externalAccessToken, externalError);
} else {
app.manage().load();
};
}
}
});
问题(S)
sammy.js
或navrouter
? 经过一天的奋斗,我得出以下结论:
VS2013 MVC 5 SPA template
似乎没有#
导航。 我设法使其正常工作,因此在这里我将总结实现方法。
虽然pagerjs
,保罗Manzotti建议,做工作得很好,我已经选择使用sammy.js
执行导航。 其他导航框架也应该工作。
因此,第一步是从nuget
获取它:
安装软件包sammy.js
安装sammy.js
之后,我们需要更改默认的VS2013 MVC 5 SPA template
的javascript
文件。 我总结一下:
首先启用sammy.js
。 有各种各样的代码放置位置选项,但是由于我想在整个应用程序中使用它,因此将其放置在: ~/Scripts/app/_run.js
如下所示:
//_run.js
$(function () {
app.initialize();
// Activate Knockout
ko.validation.init({ grouping: { observable: false } });
ko.applyBindings(app);
//provides basic '#' navigation
//run this function after the initialization of the
//default knockout code.
Sammy(function () {
//"#:view" is the parameter's name of the data after the hash tag
//it is stored in "this.params.view"
this.get('#:view', function () {
//call the navigation functions
//these are created in the default knockout initiallization
app["_navigateTo" + this.params.view]();
});
}).run("#Home");//Specify the starting page of your application
});
接下来,我希望#
导航“开箱即用”。 一个关键部分是在导航#
参数添加到url
所以,我需要在挂钩navigateTo
功能。 ~/Scripts/app/app.viewmodel.js
有一种方法:
更改:
//app.viewmodel.js
...
// Add navigation member to AppViewModel (for example, app.NavigateToHome());
self["navigateTo" + options.name] = navigator;
至:
//app.viewmodel.js
...
// Add navigation member to AppViewModel (for example, app.NavigateToHome());
// Override default routing to just set the hash
self["navigateTo" + options.name] = function() {
window.location.hash = options.name;
};
//this one is used by sammy to perform actual default routing
self["_navigateTo" + options.name] = function() {
navigator();
};
最后的细节必须确定,也就是说,当用户刷新页面时,默认路由将转到#Home
。 这是由于~/Scripts/app/app.viewmodel.js
的以下代码~/Scripts/app/app.viewmodel.js
:
//app.viewmodel.js
...
self.navigateToLoggedIn = function (userName, accessToken, persistent) {
self.errors.removeAll();
if (accessToken) {
dataModel.setAccessToken(accessToken, persistent)
}
self.user(new UserInfoViewModel(self, userName, dataModel));
//this line only routes to "#Home" when navigation
//after the login... or register, or something else
if (window.location.hash === "#Login" || window.location.hash === "#Register")
self.navigateToHome();
};
因此,在此代码中添加适当的if
语句,并且#
到位。
用来访问管理页面的正确URL为:
http://localhost:18759/#Manage
我必须说,我还没来得及给它一个适当的审查(在#
URL编码可能会被用于其他地方,并可能导致冲突)。 如果发现一些问题,我将更新此帖子。
另一点:当然,可以采用多种替代方法来连接路由。 我之所以选择这些步骤,是因为它们适用于我正在处理的情况。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.