AngularJS 1.4.6 实践 一 —— 单页应用登录验证

一、多视图路由及路由嵌套

1、多视图路由

目的:将项目主页视图与登录页面视图分离
例如:
当访问 /sigin 时将登录页面加载到 ui-view 之中;
当访问 / 时将项目页面加载到 ui-view 之中;
实现一个 ui-view 根据路由的不同加载不同页面。
在这里插入图片描述
关键代码
index.html

<div ui-view="" ></div>

app.tpl.html

<div class=app>
	<header></header>
	<div class="container-fluid-sdx">
		<div class="left-menu"></div>
		<div class="container content" ui-view="container"></div>
	</div>
</div>

routers.js

$stateProvider
.state('sigin', {
    url: 'sigin',
    templateUrl: config.tpl('sigin/sigin'),
    controllerUrl: 'ctrl/sigin/sigin',
    controller: 'sigin-sigin'
})
.state('app', {
    url: '/',
    views: {
        "@": {
            templateUrl: config.tpl('app/app')
        },
        "container@app": { // 加载content中的container视图
            templateUrl: config.tpl('search/list'),
            controllerUrl: 'ctrl/search/list',
            controller: 'search-list'
        }
    },
});

难点:本项目采用的是经典的后台管理系统布局,包括不变的头部header,左侧菜单栏Side Bar 和根据 菜单栏动态变化的内容 container。因此需要采用路由嵌套来实现动态改变一个页面内部的某一部分。

2、路由嵌套

目的:根据左侧的菜单栏动态改变右侧内容模块
例如:
当访问 /search 时将search页面加载到 ui-view = “container” 之中;
当访问 /test 时将test 页面加载到 ui-view = “container” 之中;
在这里插入图片描述
关键代码
routers.js

.state('app', {
   url: '/',
    views: {
        "@": { // 将整体布局 app.tpl.html 加载到 index.html 的 ui-view 之中
            templateUrl: config.tpl('app/app')
        },
        "container@app": { // search视图加载到app.tpl.html 中的 ui-view = "content" 之中
            templateUrl: config.tpl('search/list'),
            controllerUrl: 'ctrl/search/list',
            controller: 'search-list'
        }
    },
})
.state('app.search', {
    url: 'search',
    views: {
        "container@app": { // search视图加载到app.tpl.html 中的 ui-view = "content" 之中
            templateUrl: config.tpl('search/list'),
            controllerUrl: 'ctrl/search/list',
            controller: 'search-list'
        }
    }
})
.state('app.test', {
    url: 'test',
    views: {
        "container@app": { // test视图加载到app.tpl.html 中的 ui-view = "content" 之中
            templateUrl: config.tpl('test/index'),
            controllerUrl: 'ctrl/test/index',
            controller: 'test-index'
        }
    }
})

二、路由检测登录状态

1、添加路由改变监听事件

关键代码
routers.js

// 路由改变监听事件
$rootScope.$on('$stateChangeStart', function (event, toState) {
    if (toState.name === 'sigin') {
        return;
    }

    if (angular.isUndefined($localStorage.get('user'))) {
        event.preventDefault(); // 取消默认跳转行为
        $state.go('sigin'); // 跳转到登录界面
    }
});

2、非常重要,解决未知路径无限循环

关键代码
routers.js

$urlRouterProvider.otherwise(function ($injector) {
    var $state = $injector.get('$state');
    $state.go('app.search');
});

三、整体代码

1、index.html

<!DOCTYPE html>
<html>
<head>
    <title>语义搜索-管理系统</title>
    <meta http-equiv="content-type" content="text/html;charset=utf-8">
    <link href="/css/base.css" rel="stylesheet" type="text/css">
    <link href="/css/main.css" rel="stylesheet" type="text/css">
    <link href="/css/login.css" rel="stylesheet" type="text/css">
    <link href="//cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.3.1/semantic.min.css" rel="stylesheet">
    <link rel="shortcut icon" href="./favicon.ico" type="image/x-icon"/>
    <base href="/">
</head>
<body ng-cloak="">
<div ui-view="" class="app"></div>
<script data-main="./js/main.js?v=20180919"
        src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.2.0/require.min.js"></script>
</body>
</html>

2、sigin.tpl.html

<div class="login-view">
    <div class="login-wrapper">
        <div class="login-box">
            <div class="login-title">
                <div class="company-name">
                    <img src="/imgs/logo.png">
                    <span>语义搜索</span>
                </div>
                <div class="systme-name">
                    <span>Snack Petty Vendor</span>
                </div>
            </div>
            <div class="login-form">
                <div class="form-group form-input">
                    <input type="text" class="normal-input" id="user-name" ng-model="username" placeholder="用户名">
                    <div class="common-error-tips">
                        <div></div>
                    </div>
                </div>
                <div class="form-group form-input">
                    <input type="password" class="normal-input" id="user-pwd" ng-model="password" placeholder="密码">
                    <div class="common-error-tips">
                        <div></div>
                    </div>
                </div>
                <div class="form-group form-btn">
                    <input type="button" class="normal-btn" ng-click="sigin()" value="登录">
                </div>
                <div class="form-group form-forget">
                    <label class="error-tips">登录失败</label>
                </div>
            </div>
        </div>
    </div>
</div>

3、app.tpl.html

<div class="app">
    <header init-navbar>
        <div class="h-banner">
            <ul class="tools">
                <li><a href="javascript:;" ng-click="logout();">退出登陆</a></li>
            </ul>
        </div>
    </header>
    <div class="container-fluid-sdx">
        <div class="left-menu">
            <ul class="menu-ul">
                <li ng-repeat="v in active.nav.list">
                    <a class="menu-ul-a" href="javascript:;" ng-click="toggle=!toggle">
                        {{v.name}} <span class="arrow"></span>
                    </a>
                    <ul class="menu-ul-ul">
                        <li ng-class="{active:active.sub_navid==l.id}" data-id="{{l.id}}"
                            ng-repeat="l in v.list" ng-show="l.hasPermission && toggle">
                            <a class="menu-ul-second" ui-sref="{{l.href}}">
                                {{l.text}}
                            </a>
                        </li>
                    </ul>
                </li>
            </ul>
        </div>
        
        <div class="container content" ui-view="container"></div>
    </div>
</div>

4、routers.js

define(['oa', 'config', 'srv/local-storage'], function (pms, config) {
    pms.run(['$state', '$stateParams', '$rootScope', '$localStorage', function ($state, $stateParams, $rootScope, $localStorage) {
        $rootScope.$state = $state;
        $rootScope.$stateParams = $stateParams;
        $rootScope.active = {};

        // 路由改变监听事件
        $rootScope.$on('$stateChangeStart', function (event, toState) {
            if (toState.name === 'sigin') {
                return;
            }

            if (angular.isUndefined($localStorage.get('user'))) {
                event.preventDefault(); // 取消默认跳转行为
                $state.go('sigin'); // 跳转到登录界面
            }
        });
    }]);
    pms.config(['$stateProvider', '$urlRouterProvider', '$locationProvider', function ($stateProvider, $urlRouterProvider, $locationProvider) {
        // 非常重要,解决无限循环
        $urlRouterProvider.otherwise(function ($injector) {
            var $state = $injector.get('$state');
            $state.go('app.search');
        });

        $stateProvider
            .state('sigin', {
                url: 'sigin',
                templateUrl: config.tpl('sigin/sigin'),
                controllerUrl: 'ctrl/sigin/sigin',
                controller: 'sigin-sigin'
            })
            .state('app', {
                url: '/',
                views: {
                    "@": {
                        templateUrl: config.tpl('app/app')
                    },
                    "container@app": { // 加载content中的container视图
                        templateUrl: config.tpl('search/list'),
                        controllerUrl: 'ctrl/search/list',
                        controller: 'search-list'
                    }
                },
            })
            .state('app.search', {
                url: 'search',
                views: {
                    "container@app": { // app里name为container的view加载模版
                        templateUrl: config.tpl('search/list'),
                        controllerUrl: 'ctrl/search/list',
                        controller: 'search-list'
                    }
                }
            })
            .state('app.test', {
                url: 'test',
                views: {
                    "container@app": {//app里name为container的view加载模版
                        templateUrl: config.tpl('test/index'),
                        controllerUrl: 'ctrl/test/index',
                        controller: 'test-index'
                    }
                }
            })
        ;

        $locationProvider.html5Mode(true).hashPrefix('!');
    }]);
});

5、local-storage.js

define(['oa'], function (pms) {
    pms.service('$localStorage', ['$window', function ($window) {
        return {
            //读取单个属性
            set: function (key, value) {
                $window.localStorage[key] = value;
            },
            //存储对象,以JSON格式存储
            get: function (key, defaultValue) {
                return $window.localStorage[key] || defaultValue;
            },
            //读取对象
            setObject: function (key, value) {
                $window.localStorage[key] = JSON.stringify(value);//将对象以字符串保存
            },
            //获取字符串并解析成对象
            getObject: function (key) {
                return JSON.parse($window.localStorage[key] || '{}');
            },
            deleteLocalStorage: function (key) {
                return $window.localStorage.removeItem(key);
            }
        }
    }])
});

7、sigin.js

define(['oa', 'config'], function (oa) {
    oa.controller('sigin-sigin', ['$rootScope', '$state', '$scope', '$localStorage', function ($rootScope, $state, $scope, $localStorage) {
        $scope.sigin = function () {
        	if (!$scope.username) {
        		alert('请输入用户名');
        	}
        	
			if(!$scope.passwod){
				alert('请输入密码');
			}
        	
        	$localStorage.set('user', {
                username: $userName.val()
            });

            $state.go('search');
        };
    }]);
});
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wj11771

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值