AngularJS学习笔记

一、AngularJS

AngularJS 是谷歌开源的前端 JS 结构化框架,官网

为了方便开发可安装 chrome 插件 ng-inspector

AngularJS 版本有 1.x、2.x、4.x,其中 1.x 是基于 JavaScript,2.x、4.x 是基于 typescript,4.x 是在 2.x 基础上扩展的

1、AngularJS 的特性和优点

(1)双向数据绑定

(2)声明式依赖注入

(3)解耦应用逻辑,数据模型和视图

(4)完善的页面指令

(5)定制表单验证

(6)Ajax 封装

2、AngularJS 和 jQuery 的比较

jQuery 是 JS 函数库,作用是封装简化 DOM 操作

angular 是 JS 结构化框架,主体不再是 DOM ,而是页面中的动态数据

3、AngularJS 应用场景

AngularJS 用于构建单页面(SPA)Web 应用或 Web App 应用,如饿了么微信网页版知乎周报、后台管理应用(如阿里云、土豆后台、唯品会等)

单页面应用 SPA(Single Page Application)特点:

— 将所有活动局限于一个页面

— 当页面中有部分数据发生变化时不会刷新整个页面,而是局部刷新

— 利用的是 ajax 技术、路由

二、AngularJS 语法

1、hello world

例子:输入框中输入的文本在下方实时显示

<body ng-app>
    <input type="text" ng-model="username">
    <p><span>{{username}}</span></p>
    <script src="./angular-1.2.29/angular.js"></script>
</body>    

ng-app 指令:告诉 angular 核心它管理当前标签所包含的整个区域,并会自动创建 $rootScope 根作用域对象

ng-model 指令:ng-model 指向属性名,将当前输入框的值与当前作用域对象关联(属性名:属性值),并作为当前作用域对象($rootScope)的属性

{{ }} 表达式:显示数据,从当前作用域对象的指定属性名上获取,只能用于显示不能操作更改

2、双向数据绑定

数据绑定:数据从一个地方 A 转移(传递)到另一个地方 B,且该操作由框架完成

双向数据绑定:数据可以从 View(视图层)流向 Model(模型),也可以从 Model 流向 View

— 视图(View):就是页面(主要是 angular 指令和表达式)

— 模型(Model):作用域对象,它可以包含一些属性或方法

— 当改变 View 中的数据,Model 对象的对于属性也会随之改变:ng-model 指令数据从 View ==> Model

— 当 Model 域对象的属性发生改变时,页面对象数据随之更新:{{ }} 表达式数据从 Model ==> View

— ng-model 是双向数据绑定(View <==> Model),而 {{ }} 是单向数据绑定(Model ==> View)

ng-init 用来初始化当前作用域变量,是单向数据绑定(View ==> Model)

例子

两个输入框,每个输入框下显示输入框中的文本,更改其中一个输入框,另一个输入框以及两个输入框下的文本都改变,初始时输入框和文本为 “xxx”

<body ng-app ng-init="username='xxx'">
    <input type="text" ng-model="username">
    <p>{{username}}</p>
    <input type="text" ng-model="username">
    <p>{{username}}</p>
    <script src="./angular-1.2.29/angular.js"></script>
</body>    

3、依赖注入

依赖对象:完成某个特定功能需要某个对象才能实现,该对象就是依赖对象

依赖注入:依赖的对象以形参的形式被注入进来使用,这种方式就是声明式依赖注入

注意:形参必须是特定的名称,否则 angular 无法注入,抛出异常

angular 的 $scope 对象就是依赖对象,并且是依赖注入的形式进行使用

回调函数的 event 就是依赖对象,回调函数有形参就是依赖注入

三、三个重要对象

1、作用域对象与控制器对象

作用域对象

作用域对象是一个 js 实例对象,ng-app 指令默认会创建一个根作用域对象($rootScope)

它的属性和方法与页面中的指令或表达式是关联的

控制器对象

控制器对象用来控制 AngularJS 应用数据的实例对象的

ng-controller:指定控制器构造函数,Angular 会自动 new 此函数创建控制器对象

同时 Angular 还有创建一个新的作用域对象 $scope,它是 $rootScope 的子对象

在控制器函数中声明 $scope 形参,Angular 会自动将 $scope 对象传入

<body ng-app ng-init="age=12">
    <div ng-controller="MyController">
        <input type="text" ng-model="firstName">
        <input type="text" ng-model="lastName">
        <p>{{firstName + '-' + lastName}}</p>
        <p>{{getName()}}</p>
        <p>{{age}}</p>
    </div>
    <script type="text/javascript" src="./angular-1.2.29/angular.js"></script>
    <script type="text/javascript">
        //老版本 angular 生成作用域对象的方式
        function MyController($scope){  //形参必须是$scope
            $scope.firstName = 'aa';
            $scope.lastName = 'bb';
            $scope.getName = function(){
                return this.firstName + ' ' + this.lastName;  //也可以是 $scope.firstName + ' ' + $scope.lastName
            }
        }
    </script>
</body>

2、模块与控制器对象

angular.module 可在全局创建、注册、获取 Angular 模块,所有模块(angular 核心或第三方)都必须使用这个机制注册才能在应用中生效

模块对象可链式调用,模块对象.controller 返回值是模块对象

<body ng-app="MyApp">
    <div ng-controller="MyController1">
        <input type="text" ng-model="empName">
        <p>{{empName}}</p>
    </div>
    <div ng-controller="MyController2">
        <input type="text" ng-model="empName">
        <p>{{empName}}</p>
    </div>
    <script type="text/javascript" src="./angular-1.5.5/angular.js"></script>
    <script type="text/javascript">
        //创建模块对象
        var myModule = angular.module('MyApp',[]);
        //生成作用域对象(新版本 angular)
        myModule.controller('MyController1',function($scope){   //隐式声明依赖注入
            $scope.empName = 'aaa'
        })
        myModule.controller('MyController2',function($scope){
            $scope.empName = 'bbb'
        })
        //或使用链式调用
        //angular.module('MyApp',[])
        //    .controller('MyController1',function($scope){   //隐式声明依赖注入
        //        $scope.empName = 'aaa'
        //    })
        //    .controller('MyController2',function($scope){
        //        $scope.empName = 'bbb'
        //    })

    </script>
</body>

注意:当代码压缩时,$scope 会被 abcd等字母代替,导致 angular 解析不了,因此需要使用显式声明依赖注入,开发时需要使用该方式

angular.module('MyApp',[])
    .controller('MyController1',['$scope',function($scope){   //显式声明依赖注入
        $scope.empName = 'aaa'
    }])
    .controller('MyController2',['$scope',function($scope){
        $scope.empName = 'bbb'
    }])

四、表达式

{{表达式}} 用于显示表达式的结果数据

表达式中引用的变量必须是当前作用域对象有的属性(包括其原型属性)

可操作的数据有:

— 基本类型数据:number、string(需加引号)、boolean

— undefined、Infinity、NaN、null解析为空串,不显示任何效果

— 对象的属性或方法

— 数组

五、指令

Angular 指令是 Angular 为 HTML 页面扩展的自定义标签属性或标签

Angular 指令与 Angular 的作用域对象(scope)交互,扩展页面的动态表现力

常用指令有

ng-app:指定模块名,angular 管理的区域

ng-model:双向数据绑定,输入相关标签

ng-init:初始化数据

ng-click:点击时调用作用域对象的方法

ng-controller:指定控制器构造函数名,内部会自动创建一个新的子作用域(外部的)

ng-bind:解决使用 {{ }} 显示数据闪屏(在很短时间内显示 {{ }}

ng-repeat:遍历数组显示数据,数组有几个元素就会产生几个新的作用域,自动携带的属性有 $index(下标)、$first(布尔值)、$last(布尔值)、$middle(布尔值)、$odd(布尔值,下标为奇数时为 true)、$even(布尔值)

ng-show:布尔类型,为 true 才显示

ng-hide:布尔类型,为 true 就隐藏

<body ng-app="MyApp">
    <div ng-controller="MyController">
        <div>
            数量:<input type="number" ng-model="count">
            价格:<input type="number" ng-model="price">
            <button ng-click="getTotalPrice()">计算</button>
            <p>{{totalPrice}}</p>
        </div>

        <div>
            <ul>
                <li ng-repeat="person in persons">
                    {{$index}}---{{$even}}---{{person.username}}---{{person.age}}
                </li>
            </ul>
        </div>

        <div>
            <p>{{123}}</p>
            <p ng-bind="123"></p><!--与上行使用表达式{{}}等价-->
			
	
			

aaa

aaa

ng-class:动态引用定义的样式 {aClass:true, bClass:false} ng-style:动态应用通过 js 指定的样式对象 `ng-style="{color:'red', background:'green'}"` 或 `ng-style="作用域变量"` ng-click:点击监听,值为函数调用,可以传 $event ng-mouseenter:鼠标移入监听,值为函数调用,可以传 $event ng-mouseleave:鼠标移出监听,值为函数调用,可以传 $event
  • {{person.username}}---{{person.age}} </li> </ul> </div> <script type="text/javascript" src="./angular-1.5.5/angular.js"></script> <script type="text/javascript"> angular.module('MyApp',[]) .controller('MyController',['$scope',function($scope){ $scope.myStyle = { background: 'red' } $scope.enter = function(){ this.myStyle.background = 'green'; } $scope.leave = function(){ this.myStyle.background = 'red'; } $scope.persons = [ {username:'a',age:12}, {username:'b',age:12}, {username:'c',age:12}, ] }]) </script> </body>

其他

1、开发的两种方式

(1)命令式

更加注重的是执行的过程

(2)声明式

更加注重的是执行的结果,至于中间是如何执行的并不关心

声明式是对命令式的局部包装

命令式如同考试的解答题,声明式如同选择填空题

例子:对数组中的每个元素加 10

var arr = [1,2,3,4,5]
//命令式
var arr1 = []
for(var i = 0; i < arr.length; i++){
    var value = arr[i] + 10;
    arr1.push(value);
}
console.log(arr1);
//声明式
var arr2 = arr.map(function(item, index){
    return item + 10;
})
console.log(arr2);

2、多选框绑定数据

多选框绑定的数据会是布尔值,表示是否选中

<body ng-app="MyApp">
    <div ng-controller="MyController">
        <div ng-repeat="todo in todos">
            <input type="checkbox" ng-model="todo.isChecked">
            <span>{{todo.name}}</span>
        </div>
    </div>
    <script type="text/javascript" src="./angular-1.5.5/angular.js"></script>
    <script type="text/javascript">
        angular.module('MyApp',[])
            .controller('MyController',['$scope',function($scope){
                $scope.todos = [
                    {name:'aa', isChecked: false},
                    {name:'bb', isChecked: true},
                    {name:'cc', isChecked: false}
                ]
            }])
    </script>
</body>