您的位置:首页 > Web前端 > AngularJS

初识AngularJS

2015-05-23 22:58 127 查看
入门开始学习AngularJS,根据《AngularJS权威指南》,整理了一些学习笔记!

因为AngularJS 2.0不久前刚刚推出来,我迟疑了很久到底要不要学1.2这个版本的,最后还是决定从最原始的开始学习,先学会走,再慢慢的跑起来!

前言,一些乱七八糟的回忆

IP是互联网协议的缩写;IP地址是指每个接入到网络中的设备分配的数字标识符;

浏览器:获取网页,并将它显示给用户;

使用AngularJS,不仅可以构建页面的结构,而且可以构建用户和Web应用之间的交互;

AngularJS主要用于构建单页面的Web应用,它通过增加开发人员和常见Web应用开发任务之间的抽象级别,使构建交互式的现代Web应用变得更加简单;

AngularJS是一种构建动态Web应用的结构化框架;

AngularJS提供了一系列开发Web应用的高级功能:解耦应用逻辑、数据模型和视图,Ajax服务,依赖注入,浏览历史,测试……

AngularJs通过原生的MVC功能增强了HTML,可以快捷和愉悦地构建出令人印象深刻并且极富表现力的客户端应用;

入门应用,数据绑定{{}}

MVC:一种软件架构设计模式,将表现从用户交互中分离出来,模型(Model)中包含应用的数据与数据进行交互的办法;视图(View)将数据呈现给用户;控制器(Controler)则是二者之间的桥梁;

在MVC的世界里,控制器可以不必担心会牵扯到渲染视图工作,不必担心如何分离视图和控制器逻辑,并且也可以使测试变得既简单又令人愉悦;

AngularJS中的数据绑定

创建实时模板替代视图,而不是将数据合并进模板之后更新DOM,任何一个独立视图组件中的值都是动态替换的;

自动数据绑定使我们可以将视图理解为模型状态的映射;

AngularJS会记录数据模型所包含的数据在任何特定时间点的值,而不是原始值,它会运行自己的事件循环(调用$digest()循环,这个过程被称作“脏检查”)来检查这个值是否变“脏”,angular通过这个跟踪和响应应用变化的方式;

脏检查是检查数据模型变化的有效手段;

为了表示内部的和内置的库函数,angular使用$预定义对象;

数据模型对象$scope:其中的属性可以被视图访问,也可以同控制器进行交互;

双向数据绑定:如果视图改变了某个值,数据模型会通过脏检查观察到这个变化;如果数据模型改变了某个值,视图也会依据变化重新渲染;

[code]<DOCTYPE html>
<!--1、首先要在某个DOM元素上明确设置ng-app属性,ng-app属性声明所有被包含的内容都属于这个AngularJS应用,因此可以在Web应用中嵌套AngularJS应用,只用被ng-app属性的DOM元素包含的元素才会受AngularJS影响-->
<html ng-app>
<head>
    <title>Sample app</title>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.13/angular.js"></script>
</head>
<body>
    <!--使用ng-model指令将内部数据模型对象$scope中的name属性绑定到文本输入字段上-->
    <!--就是这么简单,完成绑定设置-->
    <input ng-model="name" type="text" placeholder="Your name">
    <h1>Hello {{ name }}</h1>
</body>
</html>


简单数据绑定

DOM元素上的ng-controller生命所有被它包含的元素都属于某个控制器

[code]<div ng-controller='MyController'>
    <input ng-model="person.name" type="text" placeholder="Your name">
    <h1>Hello {{ person.name }}</h1>
</div>


[code]//接受DOM元素的$scope和$timeout两个参数,定时器触发时会调用updateClock()函数,将$scope的值设置为当前时间
function MyController($scope, $timeout){
    var updateClock = function(){
        $scope.clock = new Date();
        $timeout(function() {
            updateClock();
        }, 1000);
    };
    updateClock();
}







数据绑定的最佳实践

clock.html

[code]<!DOCTYPE html>
<html ng-app>
<head>
    <title>time</title>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.13/angular.js"></script>
</head>
<body>
    <div ng-controller="MyController">
        <h1>Hello {{ clock.now }}!</h1>
    </div>
    <script type="text/javascript" src="scripts/clock.js"></script>
</body>
</html>


clock.js

[code]function MyController($scope){
    $scope.clock = {
        now: new Date()
    };
    var updateClock = function(){
        $scope.clock.now = new Date();
    };
    setInterval(function(){
        $scope.$apply(updateClock);
    }, 1000);
    updateClock();
}

window.onload = MyController();


模块

在angularJS中,模块是定义应用最主要的方式,模块包含了主要的应用代码;

模块的好处:保持全局命名空间的清洁;编写测试代码更容易,并能保持其清洁,以便更容易找到互相隔离的功能;易于在不同应用间复用代码;使应用能够以任意顺序加载代码的各个部分;

使用angular.module()方法来声明模块,接受两个参数:模块名、依赖列表,相当于AngularJS模块的setter方法,用来定义模块;如果只有一个参数:模块名,就可以用来引用模块,相当于AngularJS模块的getter方法,用来获取对模块的引用;

作用域,scope

作用域scope是构成AngularJS应用的核心基础;

应用的作用域是和应用的数据模型相关联的,同时作用域也是表达式执行的上下文;

$scope对象是定义应用业务逻辑、控制器方法和视图属性的地方,是视图和控制器之间的胶水;

作用域是应用状态的基础,基于动态绑定,我们可以依赖视图在修改数据时立刻更新scope,也可以依赖scope,也可以依赖scope在其发生变化时立刻重新渲染视图;

AngularJS将scope设计成和DOM类似的结构,因此scope设计成和DOM类似的结构,因此scope可以进行嵌套,我们可以引用父级$scope中的属性;

作用域提供监视数据模型变化的能力,允许开发者使用其中的apply机制,将数据模型的变化在整个应用范围内进行通知;

将应用的业务逻辑都放在控制器中,将相关的数据都放在控制器的作用域中;

视图和$scope的世界

AngularJS启动并生成视图时,会将根ng-app元素同$rootScope进行绑定,rootScope是所有scope对象的最上层;

$rootScope是AngularJS中最接近全局作用域的对象,在rootScope上附加太多业务逻辑并不是好主意,这个污染JavaScript的全局作用域是一样的;

$scope对象在AngularJS中充当数据模型,scope并不负责处理和操作数据,它只是视图和HTML之间的桥梁,是视图和控制器之间的胶水;

$scope的所有属性,都可以自动被视图访问到;

[code]<div ng-app="myApp">
    <h1> Hello {{ name }} </h1>
</div>


[code]angular.module('myApp', []){
    .run(function($rootScope){
        $rootScope.name = "World";
});


就是HTML而已

可以在AngularJS应用的模板中使用多种标记:

~指令:将DOM元素增强为可复用的DOM组件的属性或元素;

~值绑定:模板语法{{ }}可以将表达式绑定到视图上;

~过滤器:可以在视图中使用的函数,用来进行格式化;

~表单控件:用来检验用户输入的控件;

作用域能做什么

作用域的基本功能:

~提供观察者以监视数据模型的变化;

~可以将数据模型的变化通知给整个应用,甚至是系统外的组件;

~可以进行嵌套,隔离业务功能和数据;

~给表达式提供运算时所需的执行环境;

作用域包含了渲染视图时所需的功能和数据,它是所有视图的唯一源头,可以将作用域理解成视图模型;

不将变量设置在$rootScope上,而是用控制器显示创建一个隔离的子scope对象,把变量设置到这个子对象上:

[code]<!--使用ng-controller指令可以将一个控制器对象附加到DOM元素上,-->
<div ng-app="myApp">
    <div ng-controller="MyController">
        <h1>Hello {{ name }} </h1>
    </div>
</div>


[code]//创建一个控制器来管理与其相关的变量
angular.module("myApp", [])
    .controller('MyController',
    function($scope){
        $scope.name = "Cherry";
});
//ng-controller指令为这个DOM元素创建了一个新的$scope对象,并将它嵌套在$rootScope中


$scope生命周期

当Angular关心的事件发生在浏览器中时,Angular的事件循环都会启动,这个事件将在Angular执行上下文中处理;

每当事件被处理时,$scope就会对定义的表达式求值;此时事件循环会启动,并且Angular应用会监控应用程序内的所有对象,脏检查循环也会运行;

$scope对象生命周期处理的四个不同阶段:

~创建:在创建控制器或者指令时,AngularJS会用injector创建一个新的作用域,并在这个新建的控制器或指令运行时将作用域传递出去;

~链接:当Angular开始运行时,所有的scope对象都会附加或者链接到视图中,所有创建scope对象的函数也会将自身附加到视图中;

~更新:当事件循环运行时,它通常执行在顶层scope对象上,每个子作用域都会执行自己的脏值检测;每个监控函数都会检查变化,如果检查到人员变化,scope对象就会触发指定的回调函数;

~销毁:当一个scope在视图中不再需要时,这个作用域将会清理和销毁自己,使用destory()方法来清理作用域;

控制器

基本了解

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

AngularJS中的控制器是一个函数,用来向视图的作用域中添加额外的功能,我们用控制器来给作用域对象设置初始状态,并添加自定义行为;

AngularJS会在创建作用域时调用控制器方法;

只需要创建控制器作用域中的函数,就能创建可以在视图中使用的自定义操作,AngularJS运行在视图中像调用普通数据一样调用$scope上的函数;

控制器可以将与一个独立视图相关的业务逻辑封装在一个独立的容器中,尽可能精简控制器是很好的做法,使用依赖注入来访问服务可以实现这个精简目的;

控制器并不适合用来执行DOM操作、格式化或数据操作,以及除存储数据模型之外的状态维护操作,控制器只是视图和$scope之间的桥梁;

允许在$scope上设置包括对象在内的任何类型的数据,并且在视图中还可以展示对象的属性;

$scope对象用来从数据模型向视图传递信息,可以用来设置事件监听器,同应用的其他部分进行交互,以及创建与应用相关的特定业务逻辑;

AngularJS通过作用域将视图、控制器和指令隔离开来,这样就很容易为功能的具体部分编写测试;

[code]//为了不污染全局命名空间,可以创建一个模块,然后在模块中创建控制器
var app = angular.module('app', []);
app.controller('FirstController', function($scope){
    $scope.message = "hello";
});


[code]<!--按钮和链接都被绑定在了内部$scope的一个操作上,注意,当设置调用哪个函数时,会同时用括号传递一个参数(add(1))-->
<div ng-app="app">
    <div ng-controller="FirstController">
        <h4>The simplest adding machine ever</h4>
        <button ng-click="add(1)" class="button">Add</button>
        <a ng-click="subtract(1)" class="button">Subtract</a>
        <h4>Current count: {{ counter }}</h4>
    </div>
</div>


[code]var app = angular.module('app', []);
app.controller('FirstController', function($scope){
    $scope.counter = 0;
    $scope.add = function(amount){
        $scope.counter += amount;
    };
    $scope.subtract = function(amount){
        $scope.counter -= amount;
    };
});


控制器嵌套,作用域包含作用域

在指令内部创建的作用域被称作孤立作用域;

表达式

当用$watch进行监听时,AngularJS会对表达式或函数进行运算;

表达式的特性:

~所有的表达式都在其所书的作用域内部执行,并有访问本地$scope的权限;

~如果表达式发生了TypeError和ReferenceError并不会抛出异常;

~不允许使用任何流程控制功能;

~可以接受过滤器和过滤器链;

对表达式进行的任何操作,都会在其所属的作用域内部执行,因此可以在表达式内部调用那些限制在此作用域内的变量,并进行循环、函数调用、将变量应用到数学表达式中等操作;

解析AngularJS表达式

AngularJS通过$parse这个内部服务来进行表达式的运算,这个服务能访问当前所处的作用域;这个过程允许我们访问定义在scope上的原始JavaScript数据和函数;

[code]<div ng-controller="SecondController">
    <!--将一个输入框绑定到expr变量上-->
    <input ng-model="expr" type="text" placeholder="Enter an expression" />
    <h2>{{ parseValue }} </h2>
</div>


[code]var app = angular.module('app', []);
//将$parse服务注入到控制器中,然后调用它就可以实现手动解析表达式
app.controller('SecondController', function($scope, $parse){
    //给expr表达式设置一个$watch并解析它
    $scope.$watch('expr', function(newVal, oldVal, scope){
        if (newVal !== oldVal) {
            //用该表达式设置parseFun
            var parseFun = $parse(newVal);
            //获取经过解析后表达式的值
            $scope.parseValue = parseFun(scope);
        }
    })
});




插值字符串

在AngularJS中,可以手动运行模板编译的能力;

插值允许基于作用域上的某个条件实时更新文本字符串;

要在字符串模板中做插值操作,需要在对象中注入$interpolate服务;

$interpolate服务接受三个参数,第一个参数是必须的:

~text(字符串):一个包含字符插值标记的字符串;

~mustHaveExpression(布尔型):如果为true,当传入的字符串中不包含有表达式时会返回null;

~trustedContext(字符串):AngularJS会对已经进行过字符插值操作的字符串通过sec.getTrusted()方法进行严格的上下文转义;

$interpolate服务返回一个函数,用来在特定的上下文中运算表达式;

$watch函数会监视scope上的某个属性,只要属性发生变化就会调用对应的函数;可以使用watch函数在scope上某个属性发生变化时直接运行一个自定义函数;

[code]<!--希望可以在电子邮件的正文中进行实时编辑,当文本发生变化时进行字符插值操作并将结果展示出来-->
<div ng-app="app">
    <div ng-controller="ThirdController">
        <input ng-model="to" type="email" placeholder="Recipient" />
        <textarea ng-model="emailBody"></textarea>
        <pre>{{ previewText }}</pre>
    </div>
</div>


[code]var app = angular.module('app', []);
app.controller('ThirdController', function($scope, $interpolate){
    //拥有同时访问scope和interpolate服务的权限
    //因为控制器内部设置了一个需要每次变化都重新进行字符插值的自定义输入字段,因此需要设置一个$watch来监听数据的变化
    //设置$watch监视邮件正文的变化,并将emailBody属性的值进行字符插值后的结果赋值给previewText属性
    $scope.$watch('emailBody', function(body){
        if (body) {
            var template = $interpolate(body);
            $scope.previewText = template({to: $scope.to});
        }
    });
});





7. 如果需要在文本中使用不同于{{ }} 的符号来识别表达式的开始和结束,可以在$inter polateProvider中配置;

8. startSymbol()方法可以修改标识开始的符号;

9. endSymbol()方法可以修改标识结束的符号;

[code]//如果需要修改符号的设置,需要在创建新模块时将$interpolateProvider注入进去
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);
        }
    };
}]);

var app = angular.module('app', ['emailParser']);
app.controller('FourthController', ['$scope', 'EmailParser', function($scope, EmailParser){
    //设置监听
    $scope.$watch('emailBody', function(body){
        if (body) {
            $scope.previewText = EmailParser.parse(body, {
                to: $scope.to
            });
        }
    });
}]);


[code]<div ng-app="app">
    <div ng-controller="FourthController">
        <div id="emailEditor">
            <input ng-model="to" type="email" placeholder="Recipient" />
            <textarea ng-model="emailBody"> </textarea>
        </div>
        <div id="emailPreview">
            <!--将HTML修改成用这个__ 符号取代{{}}的版本-->
            <pre>__ previewText __</pre>
        </div>
    </div>
</div>


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: