簡體   English   中英

如何在MVC 5 SPA模板中使用歷史記錄進行導航?

[英]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也不起作用)。

我注意到一些可用的框架( navroutersammy.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.jsnavrouter

經過一天的奮斗,我得出以下結論:

  • 默認VS2013 MVC 5 SPA template似乎沒有#導航。

我設法使其正常工作,因此在這里我將總結實現方法。

雖然pagerjs ,保羅Manzotti建議,做工作得很好,我已經選擇使用sammy.js執行導航。 其他導航框架也應該工作。

因此,第一步是從nuget獲取它:

安裝軟件包sammy.js

安裝sammy.js之后,我們需要更改默認的VS2013 MVC 5 SPA templatejavascript文件。 我總結一下:

首先啟用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM