Angular 1.0 入门指南

Angular 1.0 入门指南

1. angular 1.0 特点

  • 数据双向绑定MVVM
  • 隔离作用域

2. Angular 的作用域 scope rootScope

先来看一下 angular 的一般使用格式

//作用域定义 模块注入
angular.module('myApp', ['ui.bootstrap']);

//获取定义的App
var app = angular.module('myApp')

//anular  加载配置  拦截器与路由的配置一般在其中
app.config(funtion(){

});


//定义服务 (注入服务)
app.factory('net', funtion($http){

});

//定义指令 (注入服务)
app.directive('jsDate', function(){

});

//定义控制器 (注入服务)
app.controller('MainCtrl', function($scope){

});

//综合 angular的定义方法
function config(){

};
function myDirective(){

};
function myService(){

};
function myController(){

};
angular.module('myApp',['ui.bootstrap'])
    .config(config)
    .run(function ($rootScope, $state) {
        $rootScope.$state = $state;
    })
    .factory('myService', myService)
    .directive('myDirective', myDirective)
    .controller('myController', myController);
2.1 $scope

$scope 是angular 中最为重要的服务,它代表着一般在angular的控制器中扮演着全局对象的作用。
下面使用实例演示$scope 的一些用法:

<input ng-model="person.name" type="text" placeholder="Yourname">
<h1>Hello {{person.name}}</h1>
//$scope 的常见用法

//监视数据的变化  ng-change 
$scope.$watch('bean', funtion(new,old){

});

//强制刷新数据 t= obj; t= function(){};
$scope.$apply(t)

$scope.$digest() 死循环来自动解析表达式

作用域(scope)①是构成AngularJS应用的核心基础. scope. scope,
也可以依赖$scope在其发生变化时立刻重新渲染视图。作用域提供了监视数据模型变化的能力。
它允许开发者使用其中的apply机制,将数据模型的变化在整个应用范围内进行通知。
我们在作用域的上下文中定义和执行表达式,同时它也是将事件通知给另一个控制器和应用其他部分的中介。
将应用的业务逻辑都放在控制器中,而将相关的数据都放在控制器的作用域中,这是非常完美的架构。

注意:AngularJS启动并生成视图时,会将根ng-app元素同 rootScope rootScope是所有$scope对象的最上层。
rootScopeAngularJS rootScope上附加太多业务逻并不是好主意,这与污染JavaScript的全局作用域是一样的。

$scope 的生命周期
- 创建

**在创建控制器或指令时,AngularJS会用$injector创建一个新的作用域**

- 链接
- 更新
- 销毁

> $scope.$destory()

指令与控制器的作用域再其所在的Dom元素上

3. 控制器 Controller

控制器在AngularJS中的作用是增强视图

  • 控制器的嵌套

    对于ng-app所处的层级来讲,它的父级作用域就是$rootScope

    作用域的嵌套是通过DOM 元素的嵌套来完成的。

<div ng-controller="ParentController">
    <div ng-controller="ChildController">
        <a ng-click="sayHello()">Say hello</a>
    </div>
    {{ person }}
</div>

控制器应该尽可能保持短小精悍,而在控制器中进行DOM操作和数据操作则是一个不好的实践。

4. 指令 directive

4.1 常见内置指令
  • ng-model ng-model-option

ng-model-options允许我们控制ng-model何时进行同步.
比如:1.当某个确定的事件被触发的时候 2.在指定的防抖动延迟时间之后,这样视图值就会在指定的时间之后被同步到模型.

失去焦点
ng-model-options="{ updateOn: 'default blur' }"
通过 debounce 延迟模型更新
ng-model-options="{debounce:1000}"

//通过 $rollbackViewValue方法 同步模型和视图
<div class="container" ng-controller="Rollback">
  <form role="form" name="myForm2" ng-model-options="{ updateOn: 'blur' }">
    <div class="form-group">
      <label>执行了 $rollbackViewValue() 方法</label>
      <input name="myInput1" ng-model="myValue1" class="form-control" ng-keydown="resetWithRollback($event)">
      <blockquote>
        <footer>myValue1: "{{ myValue1 }}"</footer>
      </blockquote>
      <p></p>
    </div>
    <div class="form-group">
      <label>没有执行了 $rollbackViewValue() 方法</label>
      <input name="myInput2" ng-model="myValue2" class="form-control" ng-keydown="resetWithoutRollback($event)">
      <blockquote>
        <footer>myValue2: "{{ myValue2 }}"</footer>
      </blockquote>
    </div>
  </form>
</div>
app.controller('Rollback',function($scope){
    $scope.resetWithRollback = function(e){
        if(e.keyCode == 27) {
            $scope.myForm2.myInput1.$rollbackViewValue();
        }
    };
    $scope.resetWithoutRollback = function(e){
        if(e.keyCode == 27){
            angular.noop()
        }
    }
});
  • ng-app ng-controller ng-view ng-include
  • ng-switch 切换文本
<input type="text" ng-model="person.name"/>
    <div ng-switch on="person.name">
    <p ng-switch-default>And the winner is</p>
    <h1 ng-switch-when="Ari">{{ person.name }}</h1>
</div>
  • ng-init
  • {{ }} ng-bind 防闪动 ng-cloak
  • ng-bind-template 用来在视图中绑定多个表达式
<div ng-bind-template="{{message}}{{name}}"></div>
  • ng-if ng-show ng-disabled ng-checked ng-readonly ng-selected
  • ng-class ng-style
  • ng-src ng-href
  • ng-form ng-submit
  • ng-click ng-dblclick
  • ng-trim
  • ng-repeat
  • ng-select ng-option 下拉选择
<div ng-controller="CityController">
    <select ng-model="city" ng-options="city.name for city in cities">
        <option value="">Choose City</option>
    </select>
    Best City: {{ city.name }}
</div>
  • ui-view 路由
  • ng-change

- ng-keydown

4.2 自定义指令

注意:指令之前的嵌套

学习指令服务 我们先来看下面 指令所拥有的所有属性。

angular.module('myApp', [])
    .directive('myDirective', function(){
        return {
            restrict:'EACM',  
            priority: Number, //优先级 默认为0
            terminal: Boolean, //
            template:'',
            templateUrl: '',
            replace: true,
            scope:{
                attr:'=', 
                ngModel:'=',//双向绑定
                option:"@", //赋值
                test:'&test' //对父级作用域进行绑定

            },
            link: function(scope, element, attr, ngModel){

            },
            controller: function($scope, $element, $attrs, $transclude){

            },
            controllerAs: String,
            require: String/[], //依赖于另一个指令 require: '?ngModel',
            //compile和link选项是互斥的。如果同时设置了这两个选项,那么会把compile所返回的函数当作链接函数,而link选项本身则会被忽略。
            //
            compile: function(tElement, tAttrs, transclude) {

            }
        }
    });

注意要点:
- scope 的绑定使用
- link 与 compile 的深入理解
- require 依赖于其他指令的封装
- require: ‘?ngModel’ 单独理解

4.3 ngModel

ngModel是一个用法特殊的指令,它提供更底层的API来处理控制器内的数据。当我们在指令中使用ngModel时能够访问一个特殊的API,
这个API用来处理数据绑定、验证、CSS更新等不实际操作DOM的事情。
ngModel控制器会随ngModel被一直注入到指令中,其中包含了一些方法。
为了访问ngModelController必须使用require设置.

angular.module('myApp')
    .directive('myDirective',function(){
        return {
            require: '?ngModel',
            link: function(scope, ele, attrs, ngModel) {
                if (!ngModel) return;
                // 现在我们的指令中已经有ngModelController的一个实例
                ngModel.$render = function() {
                    element.html(ngModel.$viewValue() || 'None');
                };
            }
        };
    });

ngModel 的属性
- $setViewValue()
- $viewValue $modelValue 二者都是ngmodel 的值 但是二者可能会不同
- $render 定义视图具体的渲染方式 慎用
- $parsers 函数组成的数组
- $formatters
- $viewChangeListeners
- $error
- $pristine
- $dirty
- $valid
- $invalid

5. 服务 service factory

5.1 内置服务
  • $http ajax 服务请求
  • $timeout 延迟执行
  • $scope 作用域
  • $rootScope 根作用于
  • $intervel 心跳定时器
  • $parse 手动解析表达式
  • $interpolate (配合表达式的解析)
  • $compile 重新构造作用域
  • $provide ,$compileProvider
angular.module('emailParser', [])
    .config(['$interpolateProvider', function($interpolateProvider) {
        $interpolateProvider.startSymbol('__');
        $interpolateProvider.endSymbol('__');
    }])
    .factory('EmailParser', ['$interpolate', function($interpolate) {
        // 处理解析的服务
        return {
            parse: function(text, context) {
            var template = $interpolate(text);
            return template(context);
            }
        };
    }]);

angular.module('myApp', ['emailParser'])
    .controller('MyController', ['$scope', 'EmailParser',
        function ($scope, EmailParser) {
            // 设置监听
            $scope.$watch('emailBody', function (body) {
                if (body) {
                    $scope.previewText = EmailParser.parse(body, {
                        to: $scope.to
                    });
                }
            });
        }]
    );
//现在用自定义的 __ 符号取代默认语法中的 {{ }} 符号来请求插值文本。

<div id="emailEditor">
    <input ng-model="to" type="email" placeholder="Recipient" />
    <textarea ng-model="emailBody"></textarea>
</div>
<div id="emailPreview">
    <pre>__ previewText __</pre>
</div>
5.2 自定义服务

6. 常见过滤器的使用 $filter 服务

6.1 常见过滤器的使用

{{ name | uppercase }}

$scope.name = $filter('lowercase')('Ari');
  • currency 货币
  • date 日期
{{ today | date:'medium' }} <!-- Aug 09, 2013 12:09:02 PM -->
{{ today | date:'short' }} <!-- 8/9/1312:09PM -->
{{ today | date:'fullDate' }} <!-- Thursday, August 09, 2013 -->
{{ today | date:'longDate' }} <!-- August 09, 2013 -->
{{ today | date:'mediumDate' }}<!-- Aug 09, 2013 -->
{{ today | date:'shortDate' }} <!-- 8/9/13 -->
{{ today | date:'mediumTime' }}<!-- 12:09:02 PM -->
{{ today | date:'shortTime' }} <!-- 12:09 PM -->

//年份格式化
四位年份:{{ today | date:'yyyy' }} <!-- 2013 -->
两位年份:{{ today | date:'yy' }} <!-- 13 -->
一位年份:{{ today | date:'y' }} <!-- 2013 -->

//月份格式化
英文月份:{{ today | date:'MMMM' }} <!-- August -->
英文月份简写:{{ today | date:'MMM' }} <!-- Aug -->
数字月份:{{ today |date:'MM' }} <!-- 08 -->
一年中的第几个月份:{{ today |date:'M' }} <!-- 8 -->

//日期格式化
数字日期:{{ today|date:'dd' }} <!-- 09 -->
一个月中的第几天:{{ today | date:'d' }} <!-- 9 -->
英文星期:{{ today | date:'EEEE' }} <!-- Thursday -->
英文星期简写:{{ today | date:'EEE' }} <!-- Thu -->

//小时格式化
24小时制数字小时:{{today|date:'HH'}} <!--00-->
一天中的第几个小时:{{today|date:'H'}} <!--0-->
12小时制数字小时:{{today|date:'hh'}} <!--12-->
上午或下午的第几个小时:{{today|date:'h'}} <!--12-->

// 分钟格式化
数字分钟数:{{ today | date:'mm' }} <!-- 09 -->
一个小时中的第几分钟:{{ today | date:'m' }} <!-- 9 -->

//秒数格式化
数字秒数:{{ today | date:'ss' }} <!-- 02 -->
一分钟内的第几秒:{{ today | date:'s' }} <!-- 2 -->
毫秒数:{{ today | date:'.sss' }} <!-- .995 -->

// 字符格式化
上下午标识:{{ today | date:'a' }} <!-- AM -->
四位时区标识:{{ today | date:'Z' }} <!--- 0700 -->
下面是一些自定义日期格式的示例:
{{ today | date:'MMMd, y' }} <!-- Aug9, 2013 -->
{{ today | date:'EEEE, d, M' }} <!-- Thursday, 9, 8-->
{{ today | date:'hh:mm:ss.sss' }} <!-- 12:09:02.995 -->
  • filer

    filter过滤器可以从给定数组中选择一个子集,并将其生成一个新数组返回

    //string 
    {{ ['Ari','Lerner','Likes','To','Eat','Pizza'] | filter:'e' }}
    
    //obj
    {{ [{'name': 'Ari','City': 'San Francisco','favorite food': 'Pizza'},
        {'name': 'Nate','City': 'San Francisco','favorite food': 'indian food'}] | filter:{'favorite food': 'Pizza'} }}
    
    //自定义函数
    {{ ['Ari','likes','to','travel'] | filter:isCapitalized }}
    $scope.isCapitalized = function(str) {
        return str[0] == str[0].toUpperCase();
    };
  • json

    son过滤器可以将一个JSON或JavaScript对象转换成字符串。这种转换对调试非常有帮助:

    {{ {'name': 'Ari', 'City': 'SanFrancisco'} | json }}
  • limitTo

    limitTo过滤器会根据传入的参数生成一个新的数组或字符串,新的数组或字符串的长度取决于传入的参数,通过传入参数的正负值来控制从前面还是从后面开始截取。

  • lowercase | uppercase

  • number 数组转换为纯文本 (参数用于控制小数点)

    {{ 123456789 | number }}
    {{ 1.234567 | number:2 }}
  • orderBy

orderBy过滤器可以用表达式对指定的数组进行排序。

orderBy可以接受两个参数,第一个是必需的,第二个是可选的。

第一个参数是用来确定数组排序方向的谓词。

第二个参数用来控制排序的方向(是否逆向)。

{{ [{'name': 'Ari','status': 'awake'},
    {'name': 'Q','status': 'sleeping'},
    {'name': 'Nate','status': 'awake'}] | orderBy:'name' }}

//结果反向
{{ [{'name': 'Ari','status': 'awake'},
    {'name': 'Q','status': 'sleeping'},
    {'name': 'Nate','status': 'awake'}] | orderBy:'name':true }}
6.2 自定义过滤器
angular.module('myApp.filters', [])
    .filter('capitalize', function() {
        return function(input) {};
    });
6.3 表单验证
  • required
  • ng-minleng
  • ng-maxleng
  • ng-pattern

使用正则表达式

<input type="text" ng-pattern="[a-zA-Z]" />
  • email
  • number
  • url

其他表单验证 以后在做讨论

7. 模块加载

服务与指令的注入与预编译实现

angular.module('myApp', [])
    .config(function($provide ,$compileProvider) {
        $provide.factory('myFactory', function() {
            var service = {};
            return service;
        });
        $compileProvider.directive('myDirective', function() {
            return {
                template: '<button>Click me</button>'
            };
        });
    });

内置路由

angular.module('myApp', [])
    .config(function($routeProvider) {
        $routeProvider.when('/', {
            controller: 'WelcomeController',
            template: 'views/welcome.html'
        });
    })
    .config(function(ConnectionProvider) {
        ConnectionProvider.setApiKey('SOME_API_KEY');
    });

运行块

和配置块不同,运行块在注入器创建之后被执行,它是所有AngularJS应用中第一个被执行的方法。

运行块通常用来注册全局的事件监听器。例如,我们会在.run()块中设置路由事件的监听器以及过滤未经授权的请求。
假设我们需要在每次路由发生变化时,都执行一个函数来验证用户的权限,放置这个功能唯一合理的地方就是run方法:

angular.module('myApp', [])
    .run(function($rootScope, AuthService) {
        $rootScope.$on('$routeChangeStart', function(evt, next, current) {
            // 如果用户未登录
            if (!AuthService.userLoggedIn()) {
                if (next.templateUrl === "login.html") {
                // 已经转向登录路由因此无需重定向
                } else {
                    $location.path('/login');
                }
            }
        });
    });

8. 多视图与路由

配置依赖 推荐使用 ui-view

<script src="js/vendor/angular-route.js"></script>  
angular.module('myApp', ['ngRoute']);  
<div ng-view></div>

完整配置

angular.module('myApp', []).config(['$routeProvider', function ($routeProvider) {
    $routeProvider
        .when('/', {
            templateUrl: 'views/home.html',
            controller: 'HomeController'
        })
        .when('/login', {
            templateUrl: 'views/login.html',
            controller: 'LoginController'
        })
        .when('/dashboard', {
            templateUrl: 'views/dashboard.html',
            controller: 'DashboardController',
            resolve: {
                user: function (SessionService) {
                    return SessionService.getCurrentUser();
                }
            }
        })
        .otherwise({
            redirectTo: '/'
        });
}]);

路由中的配置:
- controller
- template
- templateUrl
- resolve

如果设置了resolve属性,AngularJS会将列表中的元素都注入到控制器中。

resolve: {
    'data': ['$http', function($http) {
        return $http.get('/api').then(
            function success(resp) { return response.data; },
            function error(reason) { return false; }
        );
    }];
}
  • redirectTo 重定向
redirectTo: '/home'
// 或者
redirectTo: function(route,path,search)
  • reloadOnSearch boolean true $location.search()发生变化时会重新加载路由。
  • $routeParams

前面提到如果我们在路由参数的前面加上:,AngularJS就会把它解析出来并传递给$routeParams。

$routeProvider
.when('/inbox/:name', {
controller: 'InboxController',
templateUrl: 'views/inbox.html'
});
$location 服务
  • path()
  • replace() uwfa后退
  • absUrl() 编码后的完整URL
  • hash()
  • host()
  • port()
  • protocol() URL 协议
  • search() 查询串
  • url()
标签路由模式

指定路由模式

下面这种方式是使用默认的标签模式,即在url 加 # 来区分路由

angular.module('myApp', ['ngRoute'])
    .config(['$locationProvider', function($locationProvider) {
        $locationProvider.html5Mode(false);
        $locationProvider.hashPrefix('!');  //改变默认#  为!
    }]);
HTML5 路由模式

这种模式下 URL 看起来与普通的URL 一样没有区别
同样在angular 中配置路由模式

angular.module('myApp', ['ngRoute'])
    .config(['$locationProvider', function($locationProvider) {
        $locationProvider.html5Mode(true);
    }]);

9. 依赖注入

一个对象通常有三种方式可以获得对其依赖的控制权:
(1) 在内部创建依赖;
(2) 通过全局变量进行引用;
(3) 在需要的地方通过参数进行传递。

依赖注入是通过第三种方式实现的。其余两种方式会带来各种问题,例如污染全局作用域,使隔离变得异常困难等。
依赖注入是一种设计模式,它可以去除对依赖关系的硬编码,从而可以在运行时改变甚至移除依赖关系。

AngularJS使用 injetor injetor负责实例化AngularJS中所有的组件,包括应用的模块、指令和控制器等。

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页