Angular 1.6+ui-router:登录页无菜单及主页面嵌套子页面问题
解决Angular 1.6 + UI-Router的页面嵌套与权限控制问题
嘿,刚接触Angular 1.6的话,用UI-Router搞定这个需求其实挺清晰的——核心就是用嵌套状态区分两种布局(无菜单的登录类页面、带菜单的主应用页面),再结合登录状态判断来控制视图显示。我给你一步步拆解:
第一步:先调整HTML结构
首先把index.html简化成根视图容器,让不同布局都挂载在这里:
<!DOCTYPE html> <html ng-app="myApp"> <head> <!-- 你的样式、Angular/UI-Router依赖都放这里 --> </head> <body> <!-- 根视图,用来承载不同布局 --> <div ui-view></div> </body> </html>
然后新建main.html作为登录后的主布局,里面包含菜单、导航栏、页脚,再留一个子视图用来加载具体页面:
<!-- 顶部导航/菜单 --> <nav class="app-nav"> <a ui-sref="main.home">首页</a> <a ui-sref="main.profile">个人中心</a> <button ng-click="logout()">退出</button> </nav> <!-- 子视图:这里会加载登录后的具体页面 --> <div ui-view="content"></div> <!-- 页脚 --> <footer class="app-footer">© 2024 我的应用</footer>
登录/注册/找回密码页面就保持独立的无布局样式,比如login.html:
<div class="login-box"> <h2>登录</h2> <input type="text" ng-model="username" placeholder="账号"> <input type="password" ng-model="password" placeholder="密码"> <button ng-click="login()">登录</button> </div>
第二步:在app.js里配置UI-Router状态
这是核心步骤,我们要定义抽象状态作为主布局的父容器,把登录后的页面设为它的子状态;登录类页面作为独立的顶级状态。
angular.module('myApp', ['ui.router']) .config(function($stateProvider, $urlRouterProvider) { // 默认路由:未登录时跳登录页 $urlRouterProvider.otherwise('/login'); // 1. 定义主布局的抽象状态(不能直接访问,只能作为子状态的父容器) $stateProvider.state('main', { abstract: true, templateUrl: 'main.html', controller: 'MainController', // 路由守卫:未登录的话直接跳登录页 resolve: { checkLogin: function($state, AuthService) { if (!AuthService.isLoggedIn()) { $state.go('login'); } } } }) // 2. 主布局下的子页面:首页 .state('main.home', { url: '/home', views: { // 指定加载到main状态下的content视图 'content@main': { templateUrl: 'home.html', controller: 'HomeController' } } }) // 主布局下的子页面:个人中心 .state('main.profile', { url: '/profile', views: { 'content@main': { templateUrl: 'profile.html', controller: 'ProfileController' } } }) // 3. 登录状态(顶级状态,无菜单布局) .state('login', { url: '/login', templateUrl: 'login.html', controller: 'LoginController', // 路由守卫:已登录的话直接跳首页 resolve: { redirectIfLoggedIn: function($state, AuthService) { if (AuthService.isLoggedIn()) { $state.go('main.home'); } } } }) // 注册状态 .state('register', { url: '/register', templateUrl: 'register.html', controller: 'RegisterController' }) // 找回密码状态 .state('forgotPassword', { url: '/forgot-password', templateUrl: 'forgot-password.html', controller: 'ForgotPasswordController' }); });
第三步:实现登录状态管理服务
你需要一个AuthService来存登录状态,实际项目里可以用localStorage存token,这里先模拟:
angular.module('myApp') .service('AuthService', function() { // 模拟登录状态,实际项目替换为token验证 let loggedIn = false; this.login = function(username, password) { // 这里写实际的登录请求逻辑,比如调用后端接口 // 登录成功后设置状态 loggedIn = true; return Promise.resolve(); }; this.isLoggedIn = function() { return loggedIn; }; this.logout = function() { loggedIn = false; }; });
第四步:完善登录控制器的跳转逻辑
登录成功后,直接跳转到主布局下的首页:
angular.module('myApp') .controller('LoginController', function($scope, $state, AuthService) { $scope.login = function() { AuthService.login($scope.username, $scope.password) .then(() => { // 登录成功跳转到main.home $state.go('main.home'); }) .catch(err => { $scope.errorMsg = '登录失败,请检查账号密码'; }); }; });
关键逻辑说明
- 抽象状态
main:它是所有登录后页面的父容器,加载带菜单的main.html,子状态的内容会自动嵌套到main.html的ui-view="content"里。 - 路由守卫
resolve:用来控制页面访问权限——未登录的用户进不了main的子页面,已登录的用户访问登录页会直接跳首页。 - 视图命名规则:
'content@main'表示把模板加载到main状态下名为content的视图,确保页面嵌套不会出错。
这样配置后,登录/注册/找回密码页面会直接显示在根视图里(没有菜单),登录成功后进入main的子状态,自动加载带菜单的布局,具体页面也会正确嵌套进去。
内容的提问来源于stack exchange,提问作者Miguel-Ángel
相关产品推荐
相关产品推荐

