MVC SPA + Нокаут

Недавно мне было поручено создать SPA. Итак, я создал новый проект и выбрал SPA и обнаружил, что он загрузил все файлы, которые мне нужны, включая этот knockout.js.

Я новичок в knockout.js, поэтому я просмотрел несколько видеороликов, и я понял эту идею, но проект SPA просто не вычисляется для меня, поскольку это не приложение для одной страницы, потому что вам нужно перейти к новому URL-адресу для входа, регистрации, авторизации, управления учетной записью и т.д. (вы получаете идею).

Итак, глядя на код для индексной страницы, я вижу модель представления для 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 выглядит так:

теперь, с точки зрения этого (исправьте меня, если я ошибаюсь), с дескриптором указано, что если есть переменная, называемая 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, когда кто-либо перебирается на #draw, тогда частичная часть дома не будет отображаться, аналогично, я мог бы добавить app.draw = null в маршрут sammy для homeViewModel, чтобы скрыть частичный результат,

Моя проблема с этим заключается в том, что он будет значительно сложнее, чем больше viewModels, которые я создаю. Итак, есть что-то, чего я не хватает? Есть ли более простой способ сделать это?

Моя конечная цель - переместить все страницы в SPA (включая страницы входа/регистрации).

Приветствия заранее, /r3plica

1 ответ

Ну, после немного беспорядка я узнал, как это сделать. В основном я переписал метод 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') });
});

licensed under cc by-sa 3.0 with attribution.