4

AngularJS

AngularJS基础

AngularJS简介

AngularJS是一个用于构建单页面应用的前端JS框架,在前端践行了MVC设计模式。
AngularJS是一个前端JS框架,或者叫做一个JS库,可以通过script标签的形式引用到HTML页面上。
AngularJS与Angular2以上为两套不同的框架体系

<script src="https://cdn.bootcss.com/angular.js/1.6.3/angular.js"></script>

AngularJS是一些以Misko Hevery为首的后端程序员开发出来的前端框架,后被谷歌公司收购并广泛应用于谷歌的各种大小项目。

多页面应用和单页面应用

图片描述
多页面应用和单页面应用的页面结构对比

一个AngularJS简单应用
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>第一个AngularJS简单应用</title>
    <script src="https://cdn.bootcss.com/angular.js/1.6.3/angular.js"></script>
</head>
<body>
    <!--ng-app声明Angular的作用范围-->
    <div ng-app>
        <!--ng-model来将输入框里的内容绑定给变量name-->
        <input type="text" ng-model="name">
        <div>
            <!--字符串模板,用于在页面上直接显示变量内容-->
            你好,{{name}}<br>
            <!--字符串模板中的内容是AngularJS表达式(包含JS表达式)-->
            {{1 + 1}}<br>
            {{3>2?"3大于2":"3不大于2"}}
        </div>
    </div>
</body>
</html>
ng-app

ng-app用来声明当前页面中angular应用的作用范围, 可以写在包括<html><body>的所有标签上,这时,这个标签和其字标签就都在angular应用的作用范围之内了。

AngularJS核心特性

AngularJS通过 指令字符串模板数据模型(Model)视图(View) 中的对应的数据 双向绑定

指令

指令 就是以 ng- 开头的一些扩展HTML标签属性,比如 ng-appng-model 。在标签上使用指令,就可以让标签具有一些AngularJS提供的功能。

字符串模板

字符串模板 就是以被 {{}} 包含的一些 AngularJS表达式AngularJS表达式 包括JS表达式和AngularJS专有的特殊表达式。

双向绑定

视图(View) 上显示的内容发生变化时,数据模型(Model) 中相应的变量会随之变化。
数据模型(Model) 中的变量发生变化时,视图(View) 上显示的内容会随之变化。

MVC设计模式

MVC设计模式说明
图片描述

第一个AngularJS正式应用

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>第一个AngularJS正式应用</title>
    <script src="https://cdn.bootcss.com/angular.js/1.6.3/angular.js"></script>
</head>
<body>
    <!--ng-app声明Angular的作用范围,如果不想使用默认的AngularJS控制器,就要给ng-app起一个名字-->
    <!--ng-controller声明自定义控制器的作用范围,必须使用as给控制器起一个别名-->
    <div ng-app="myApp" ng-controller="myCtrl as mc">
        <!--在当前控制器作用范围内,可以使用别名访问控制器的属性-->
        {{mc.name}}
        <!--字符串模板也可以应用在标签的普通属性中-->
        <img src="head.jpg" title="{{mc.imgTip}}">
    </div>
    <script>
        "use strict";
        //获取页面中的应用,作为AngularJS的控制区域
        var myApp = angular.module("myApp",[]);
        //为APP对象提供一个Controller
        //第二个参数,是Controller的构造函数
        myApp.controller("myCtrl",function(){
            //为了避免this指向改变造成的问题并且使用起来更加方便,将this转存
            var mc = this;

            mc.name = "lins";
            mc.imgTip = "这是我的头像";
        });
    </script>
</body>
</html>
angular.module

用于创建或者获取指定的angular应用。

//创建: angular.moudle("ng-app的值,即应用的名字",["配置信息"]);
angular.module("myApp",[]);//注:即使没有配置信息,也要写一个空数组

//获取: angular.moudle("ng-app的值,即应用的名字");
angular.module("myApp");
controller

用于向应用添加控制器。

//myApp.controller("控制器名字",构造函数);
myApp.controller("myCtrl",function(){
    //为了避免this指向改变造成的问题并且使用起来更加方便,将this转存
    var mc = this;

    mc.属性名 = 值;
    mc.函数名 = function(){

    };
});

AngularJS应用程序开发步骤

1、引用AngularJS库。
2、ng-app、ng-controller。
3、创建应用程序、添加控制器。
4、双向绑定。

AngularJS初级语法

使用ng-repeat展示数组中的数据

语法:

<!--简单数组-->
<标签 ng-repeat="引用 in 数组">{{引用}}</标签>
<!--对象的数组-->
<标签 ng-repeat="引用 in 数组">{{引用.属性}}</标签>
展示简单数组
  <div ng-app="myApp" ng-controller="myCtrl as mc">
      <ul>
          <!--ng-repeat会将所在的标签及其子标签根据数组元素的个数进行复制-->
          <li ng-repeat="i in mc.array">{{i}}</li>
      </ul>
  </div>
  <script>
      "use strict"
      var myApp = angular.module("myApp",[]);
      myApp.controller("myCtrl",function(){
          var mc = this;
          mc.array = [0,1,3,52];
      });
  </script>
展示对象的数组
<div ng-app="myApp" ng-controller="myCtrl as mc">
    <table border="1px">
        <tr>
            <td>序号</td>
            <td>用户名</td>
            <td>年龄</td>
        </tr>
        <tr ng-repeat="u in mc.users">
            <!--$index是ng-repeat语法中的特殊属性,指当前遍历的下标,number类型,从0开始-->
            <td>{{$index + 1}}</td>
            <td>{{u.name}}</td>
            <td>{{u.age}}</td>
        </tr>
    </table>
</div>
<script>
    "use strict"
    var myApp = angular.module("myApp",[]);
    myApp.controller("myCtrl",function(){
        var mc = this;
        mc.users = [
            {name:"lins",age:24},
            {name:"suns",age:18},
            {name:"zhang3",age:18}
        ];
    });
</script>
展示简单数组时的注意事项

当简单数组中有两个 等价 (类似于===,但是NaN等价于NaN)的元素时,需要track by 每次遍历时唯一的值以进行区别。

<div ng-app="myApp" ng-controller="myCtrl as mc">
    <ul>
        <!--$index是当前遍历的下标,可以作为每次遍历时唯一的值-->
        <li ng-repeat="i in mc.array track by $index">{{i}}</li>
    </ul>
</div>
<script>
    "use strict"
    var myApp = angular.module("myApp",[]);
    myApp.controller("myCtrl",function(){
        var mc = this;
        mc.array = [0,1,3,52,3];
    });
</script>
ng-repeat中的其他特殊属性**

在ng-repeat中,除了$index是常用的number型特殊属性外,还有5种boolean型的特殊变量供我们使用。

特殊属性 为true条件
$first 遍历时的第一个(即下标为0)
$last 遍历时的最后一个(即下标为length-1)
$odd 下标为奇数的(注意下标从0开始,即传统意义上的偶数)
$even 下标为偶数的(注意下标从0开始,即传统意义上的奇数)
$middle 遍历时除了第一个和最后一个(0 < 下标 < length - 1)

根据条件展示

AngularJS可以根据某个表达式的结果决定某部分内容是否显示。这种特性在许多场景下都有重要应用,常见的是用于在服务器端数据未加载完成时显示提示信息。

AngularJS用了两种不同的方式来实现这一特性。

  • 根据表达式的结果,决定是否动态创建这个DOM元素: ng-if 和 ng-switch 。
  • 根据表达式的结果,决定是否显示这个标签: ng-show 和 ng-hide 。
两种方式比较
  • 动态创建DOM的效率比修改标签显示方式的效率低很多。
  • 动态创建DOM的方式能避免极个别情况下的样式错误或逻辑错误。

因此需要根据使用场景来决定采取何种方式。

ng-if

语法:

<!--为true显示,为false不显示-->
<标签 ng-if="布尔表达式"></标签>

例子:

<div ng-app="myApp" ng-controller="myCtrl as mc">
    <div ng-if="mc.myVar==1">ng-if 1</div>
    <div ng-if="mc.myVar==2">ng-if 2</div>
    <div ng-if="mc.myVar==3">ng-if 3</div>
</div>
<script>
    "use strict"
    var myApp = angular.module("myApp",[]);
    myApp.controller("myCtrl",function(){
        var mc = this;
        mc.myVar = 2;
    });
</script>
ng-switch

语法:

<标签 ng-switch="表达式">
    <!--根据表达式的结果匹配显示对应标签,当都不匹配时,显示default对应的(如果有)-->
    <标签 ng-switch-when="值1"></标签>
    <标签 ng-switch-when="值2"></标签>
    <标签 ng-switch-default></标签>
</标签>

例子:

<body>
    <div ng-app="myApp" ng-controller="myCtrl as mc">
        <div ng-switch="mc.test">
            <div ng-switch-when="1">1</div>
            <div ng-switch-when="2">2</div>
            <div ng-switch-default>默认</div>
        </div>
    </div>
<script>
    "use strict"
    var myApp = angular.module("myApp",[]);
    myApp.controller("myCtrl",function(){
        var mc = this;
        mc.test = 1;
    });
</script>
ng-show

语法:

<!--为true显示,为false不显示-->
<标签 ng-show="布尔表达式"></标签>

例子:

<div ng-app="myApp" ng-controller="myCtrl as mc">
    <div ng-show="mc.myVar==1">ng-show 1</div>
    <div ng-show="mc.myVar==2">ng-show 2</div>
    <div ng-show="mc.myVar==3">ng-show 3</div>
</div>
<script>
    "use strict"
    var myApp = angular.module("myApp",[]);
    myApp.controller("myCtrl",function(){
        var mc = this;
        mc.myVar = 2;
    });
</script>
ng-hide**

ng-show的反逻辑,即为true不显示,为false显示。不常用。

特殊属性绑定

ng-src和ng-href

ng-src 用于代替图片的src属性,用于防止数据加载完毕前的错误图像显示。
ng-href 用于代替链接的href属性,用于防止数据加载完毕前的错误链接指向。

<div ng-app="myApp" ng-controller="myCtrl as mc">
    <img ng-src="{{mc.image}}">
    <a ng-href="{{mc.url}}">链接</a>
</div>
<script>
    "use strict"
    var myApp = angular.module("myApp",[]);
    myApp.controller("myCtrl",function(){
        var mc = this;
        mc.image = "head.jpg";
        mc.url = "http://www.baidu.com";
    });
</script>
ng-class

ng-class 可以使用扩展的AngularJS表达式来更加智能的动态控制标签样式。包括单值语法数组语法对象语法

单值语法
<!--直接将属性的值作为class-->
<标签 ng-class="某个属性"></标签>
数组语法
<!--将数组中所有的元素的值作为class,自动使用空格分隔-->
<标签 ng-class="[属性1,属性2]"></标签>
对象语法
<!--根据布尔表达式动态控制class,当某个属性值为true时,相应的属性名会加入class-->
<标签 ng-class="{'样式名称1':布尔表达式1,'样式名称2':布尔表达式2}"></标签>

绑定表单元素

ng-model 可以双向绑定表单元素。

普通文本框

<input type="text" ng-model="mc.name">
<input type="password" ng-model="mc.pass">

单选框

<div ng-app="myApp" ng-controller="myCtrl as mc">
    <input type="radio" ng-model="mc.r" value="1">1
    <input type="radio" ng-model="mc.r" value="2">2
    <input type="radio" ng-model="mc.r" value="3">3
    <br>
    {{mc.r}}
</div>
<script>
    "use strict"
    var myApp = angular.module("myApp",[]);
    myApp.controller("myCtrl",function(){
        var mc = this;

        //可以进行默认选中,注意必须是字符串的值
        mc.r = "2";
    });
</script>

多 选框

注意:对于多选框,ng-model只能绑定其checked属性(true或false。 因此,如果想要进行默认选中,一般需要使用另一个指令 ng-checked ;并且,多个选择框不要使用同样的ng-model值,否则会发生联动。

由于这种特性,故多选框不适合用来做表单提交,多用于结合ng-if或ng-show来做出选中时显示额外内容的效果。

<div ng-app="myApp" ng-controller="myCtrl as mc">
    <input type="checkbox" ng-model="mc.c1" value="a" ng-checked="mc.ca == 1">A
    <input type="checkbox" ng-model="mc.c2" value="b" ng-checked="mc.cb == 2">B
    <input type="checkbox" ng-model="mc.c3" value="c" ng-checked="mc.cc == 3">C
    <br>
    mc.c1:{{mc.c1}}<br>
    mc.c2:{{mc.c2}}<br>
    mc.c3:{{mc.c3}}<br>
</div>
<script>
    "use strict"
    var myApp = angular.module("myApp",[]);
    myApp.controller("myCtrl",function(){
        var mc = this;

        mc.c2 = true;
        mc.cb = "2";
    });
</script>

下拉列表框

  • 当option标签没有value属性时,ng-model和标签体绑定,取值和默认赋值依据标签体进行。
  • 当option标签有value属性时,ng-model和value属性绑定,取值和默认赋值依据value属性进行。
<div ng-app="myApp" ng-controller="myCtrl as mc">
    <select ng-model="mc.s1">
        <option>A</option>
        <option>B</option>
        <option>C</option>
    </select>
    <span>{{mc.s1}}</span>
    <select ng-model="mc.s2">
        <option value="aa">AA</option>
        <option value="bb">BB</option>
        <option value="cc">CC</option>
    </select>
    <span>{{mc.s2}}</span>
</div>
<script>
    "use strict"
    var myApp = angular.module("myApp",[]);
    myApp.controller("myCtrl",function(){
        var mc = this;  

        mc.s1 = "C";
        mc.s2 = "aa";
    });
</script>

AngularJS对事件的封装

绑定到控制器属性中的函数,除了可以在控制器中直接调用外,更多的应用是作为事件的处理函数。使用AngularJS封装的事件(也是一种AngularJS指令),可以直接处理AngularJS管理的各种动态数据。

例子:

<div ng-app="myApp" ng-controller="myCtrl as mc">
    <input type="text" ng-model="mc.text">
    <button ng-click="mc.btn_click()">加入</button>
    <ul>
        <li ng-repeat="txt in mc.array">{{txt}}</li>
    </ul>
</div>
<script>
    "use strict"
    var myApp = angular.module("myApp",[]);
    myApp.controller("myCtrl",function() {
        var mc = this;

        mc.array = [];
        mc.btn_click = function () {
            mc.array.push(mc.text);
            mc.text = "";
        }
    });
</script>

AngularJS事件型指令列表

事件(指令) 触发时机 触发元素
ng-click 鼠标单击 任意标签
ng-dblclick 鼠标双击 任意标签
ng-mouseenter 鼠标移入 任意标签
ng-mouseleave 鼠标移出 任意标签
ng-mousemove 鼠标移动 任意标签
ng-change 表单元素中用户输入的数据每次被改变 表单元素
ng-copy 在多种情况下触发,包括复制、选中等 表单元素
ng-cut 表单元素中用户输入的数据每次被剪切 表单元素
ng-paste 表单元素中用户输入的数据每次被粘贴 表单元素
ng-focus 表单元素每次获得焦点 表单元素
ng-blur 表单元素每次失去焦点 表单元素

注:ng-change必须配合ng-model使用。

AngularJS中级语法

AngularJS的代码侵入性比较强,很难兼容于类似于jQuery之类的其他前端框架。故不能使用jQuery来操作AngularJS中管理的数据。

依赖注入简介

依赖注入(Dependency Injection,简称DI)是指一个功能需的一些功能组件(对象、函数等)不是由这个功能本身创建,而是由其他功能创建。前者无需关心这一功能组件的实现。
最简单的依赖注入的例子就是调用函数时传参:函数无需关心传入的参数是如何得来的,只需要声明这个参数,就可以直接使用

服务

服务 在AngularJS中是一个函数或一个对象,它可以依赖注入到任何需要使用它的控制器中。
AngularJS提供的服务以$开头。常用的有 $timeout、$interval 、$scope、$rootScope和$http。

$timeout和$interval

在AngularJS中,不能直接使用setTimeout和setInterval来操作AngularJS中的动态变量。 如果需要类似这样的功能,需要使用AngularJS的$timeout和$interval服务。

例子:

<div ng-app="myApp" ng-controller="myCtrl as mc">
    {{mc.test}}
</div>
<script>
    "use strict"
    var myApp = angular.module("myApp",[]);
    myApp.controller("myCtrl",function($timeout,$interval){
        var mc = this;

        mc.test = 1;
        var p1 = $timeout(function(){
            mc.test ++;
        },2000);
        var p2 = $interval(function() {
            mc.test ++;
        },500);

        $timeout.cancel(p1);
        $interval.cancel(p2);
    });
</script>
解决代码压缩引发的依赖注入的问题

由于依赖注入是根据声明自动注入的,因此要求形参的名字必须完全一致。然而js代码经过压缩后,会自动变更形参的名字,使得注入失效。AngularJS也针对这种情况提出来一种新的写法, 当我们使用依赖注入时,务必要采取这种写法 。

写一个数组,将被注入的函数为数组的最后一个元素。将注入的服务写成形参的同时以字符串的形式作为数组的前几个元素, 并且这几个字符串和形参保持顺序一致 。
如上例可以写成这样:

<div ng-app="myApp" ng-controller="myCtrl as mc">
    {{mc.test}}
</div>
<script>
    "use strict"
    var myApp = angular.module("myApp",[]);
    myApp.controller("myCtrl",["$timeout","$interval",function($timeout,$interval){
        var mc = this;

        mc.test = 1;
        var p1 = $timeout(function(){
            mc.test ++;
        },2000);
        var p2 = $interval(function() {
            mc.test ++;
        },500);

        $timeout.cancel(p1);
        $interval.cancel(p2);
    }]);
</script>
$scope**

$scope是作用域,每个controller都有一个作用域,ng-repeat等一些比较特殊的指令也会创建新的子作用域,ng-model和ng-init也可以直接把一些数据直接绑定到作用域中。 ** 在一些比较大的AngularJS项目中,作用域的关系错综复杂,因此不建议大家使用$scope和ng-init。**

例子:

<div ng-app="myApp" ng-controller="myCtrl as mc">
    <!--绑定到作用域中的属性可以直接像这样访问-->
    {{name}}
</div>
<script>
    "use strict"
    var myApp = angular.module("myApp",[]);
    myApp.controller("myCtrl",["$scope",function($scope){
        $scope.name = "lins";
    }]);
</script>
$rootScope

$rootScope也是作用域,不过是每个app有且只有一个的 根作用域 ,由于在每个控制器中都能访问这唯一的一个作用域,因此可以用来跨控制器传值。

例子:

<div ng-app="myApp">
    <div ng-controller="myCtrl1 as mc1">
        <!--不能在页面上直接向rootScope中存值,必要时可以通过事件中转-->
        <input type="text" ng-change="mc1.txt_change()" ng-model="mc1.text">
    </div>
    <div ng-controller="myCtrl2 as mc2">
        <!--在页面上取值时,与$scope用法相似,直接写属性名就可以-->
        {{text}}
        <button ng-click="mc2.btn_click()">console.log</button>
    </div>
</div>
<script>
    "use strict"
    var myApp = angular.module("myApp",[]);
    myApp.controller("myCtrl1",["$rootScope",function($rootScope){
        var mc1 = this;
        mc1.txt_change = function(){
            //在JS代码中,需要将$rootScope服务注入到想要使用的controller中
            //就可以像使用其他对象一样的存值方式和取值方式。
            $rootScope.text = mc1.text;
        }
    }]);
    myApp.controller("myCtrl2",["$rootScope",function($rootScope){
        var mc2 = this;
        mc2.btn_click = function(){
            console.log($rootScope.text);
        }
    }]);
</script>
$http

$http是AngularJS对ajax的封装,用来向服务器发送请求。

GET请求

"use strict"
var myApp = angular.module("myApp",[]);
myApp.controller("myCtrl",["$http",function($http){
    var mc = this;
    $http({
        url:"http://127.0.0.1/param?name=lins&age=24",
        method:"GET"
    }).then(function(resp){
        //成功时的回调函数
        //resp.data就是服务器以json形式发送的对象
        console.log(resp.data);

        //服务器返回的数据可以交给AngularJS进行管理,以便在页面上渲染
        mc.users = resp.data;
    },function(err){
        //失败时的回调函数
    });
}]);

POST请求

"use strict"
var myApp = angular.module("myApp",[]);
myApp.controller("myCtrl",["$http",function($http){
    var mc = this;
    $http({
        url:"http://127.0.0.1/httpServer/param",
        method:"POST",
        data:"name=lins&age=24",
        //配置请求方式为模拟表单
        headers:{"Content-Type":"application/x-www-form-urlencoded"}
    }).then(function(resp){
        console.log(resp.data);
        mc.users = resp.data;
    },function(err){
        //失败时的回调函数
    });
}]);

从页面收集参数**

<html>
<head>
    <meta charset="UTF-8">
    <title>从页面收集参数</title>
    <script src="https://cdn.bootcss.com/angular.js/1.6.3/angular.js"></script>
    <script src="querystring.js"></script>
</head>
<body>
    <div ng-app="myApp" ng-controller="myCtrl as mc">
        用户名:<input type="text" ng-model="mc.user.username"><br>
        密码:<input type="password" ng-model="mc.user.password"><br>
        性别:
        <input type="radio" ng-model="mc.user.gender" value="male">男
        <input type="radio" ng-model="mc.user.gender" value="female">女
        <button ng-click="mc.submit()">提交</button>
        <br>
    </div>
    <script>
        "use strict"
        var myApp = angular.module("myApp",[]);
        myApp.controller("myCtrl",["$http",function($http){
            var mc = this;

            mc.submit = function(){
                $http({
                    url:"http://127.0.0.1/httpServer/param",
                    method:"POST",
                    data:querystring.stringify(mc.user),
                    headers:{"Content-Type":"application/x-www-form-urlencoded"}
                });
            };
        }]);
    </script>
</body>
</html>

过滤器

有时,我们想要某些数据,在显示到页面上之前进行统一处理。这时,再依赖控制器实现,往往过于繁琐。AngularJS为了解决这种问题,提出了过滤器的概念。

货币格式过滤器currency
<div ng-app="myApp" ng-controller="myCtrl as mc">
    <!--使用过滤器时,使用|与原始数据分隔-->
    <span>{{mc.c1 | currency}}</span>
    <!--传参数时,使用:分隔-->
    <span>{{mc.c2 | currency:"¥"}}</span>
    <span>{{mc.c3 | currency:"$":4}}</span>
</div>
<script>
    "use strict"
    var myApp = angular.module("myApp",[]);
    myApp.controller("myCtrl",function(){
        var mc = this;

        mc.c1 = 15;
        mc.c2 = 26.7;
        mc.c3 = 35.66;
    })
</script>
在JS中使用过滤器

过滤器的一般用法是在页面上(视图层)直接使用,同时,它也可以作为一种服务注入到控制器中使用。

"use strict"
var myApp = angular.module("myApp",[]);
myApp.controller("myCtrl",function($filter){
    //语法:$filter("过滤器名字")(要过滤的数据,参数1,参数2,...)
    console.log($filter("currency")(15,"¥",3));
});
日期格式过滤器
<div ng-app="myApp" ng-controller="myCtrl as mc">
    <span>{{mc.now | date:"yyyy-MM-dd HH:mm:ss"}}</span>
</div>
<script>
    "use strict"
    var myApp = angular.module("myApp",[]);
    myApp.controller("myCtrl",function(){
        var mc = this;

        mc.now = new Date();
    })
</script>
数组排序过滤器
<div ng-app="myApp" ng-controller="myCtrl as mc">
    <ul>
        <!--根据数组元素本身从小到大排序-->
        <li ng-repeat="i in mc.array | orderBy">{{i}}</li>
    </ul>
    <ul>
        <!--根据数组元素本身从大到小排序-->
        <li ng-repeat="i in mc.array | orderBy:'-'">{{i}}</li>
    </ul>
    <table border="1">
        <tr>
            <td>姓名</td>
            <td>年龄</td>
        </tr>
        <!--根据数组元素某个属性从小到大排序-->
        <tr ng-repeat="u in mc.users | orderBy:'age'">
            <td>{{u.name}}</td>
            <td>{{u.age}}</td>
        </tr>
    </table>
    <br>
    <table border="1">
        <tr>
            <td>姓名</td>
            <td>年龄</td>
        </tr>
        <!--根据数组元素某个属性从大到小排序-->
        <tr ng-repeat="u in mc.users | orderBy:'-age'">
            <td>{{u.name}}</td>
            <td>{{u.age}}</td>
        </tr>
    </table>
</div>
<script>
    "use strict"
    var myApp = angular.module("myApp",[]);
    myApp.controller("myCtrl",function(){
        var mc = this;

        mc.array = [1,3,2,8,5];
        mc.users = [
            {name:"lins",age:24},
            {name:"suns",age:18},
            {name:"zhang3",age:35}
        ];
    });
</script>
数组查找过滤器
<div ng-app="myApp" ng-controller="myCtrl as mc">
    <ul>
        <!--根据数组元素本身进行查找-->
        <li ng-repeat="i in mc.array | filter:1">{{i}}</li>
    </ul>
    <table border="1">
        <tr>
            <td>姓名</td>
            <td>年龄</td>
        </tr>
        <!--根据数组元素的某个属性进行查找-->
        <tr ng-repeat="u in mc.users | filter:{name:'s'}">
            <td>{{u.name}}</td><td>{{u.age}}</td>
        </tr>
    </table>
</div>
<script>
    "use strict"
    var myApp = angular.module("myApp",[]);
    myApp.controller("myCtrl",function($filter){
        var mc = this;

        mc.array = [11,12,23,45,51];
        mc.users = [
            {name:"lins",age:24},
            {name:"suns",age:18},
            {name:"licy",age:24}
        ];
    })
</script>
自定义过滤器

有时,AngularJS提供的过滤器并不能满足我们的需求。这时,我们就可以自定义过滤器。

<div ng-app="myApp" ng-controller="myCtrl as mc">
    <div>{{mc.test | price}}</div>
</div>
<script>
    "use strict"
    var myApp = angular.module("myApp",[]);
    //myApp.filter("过滤器名字",function(){
    //    return 过滤器实现函数(原始数据,所需参数1,...){
    //        return 处理完的数据;
    //    }
    });
    myApp.filter("price",function(){
        return function(text,prefix,count){
            prefix = prefix || "¥";
            count = count || 2;
            //在这里将处理好的数据进行返回
            return prefix + parseFloat(text).toFixed(count);
        }
    });
    myApp.controller("myCtrl",function(){
        var mc = this;

        mc.test = 5;
    })
</script>

AngularJS高级语法

路由

图片描述

路由描述了url和视图的映射关系。

AngularJS对路由的实现
<script src="https://cdn.bootcss.com/angular-ui-router/1.0.3/angular-ui-router.js"></script>

AngularJS的路由系统,由一个主页面和若干个子页面构成。所有的JS代码和CSS代码放在主页面上,子页面仅仅完成制作视图的功能。
AngularJS对路由的实现是通过URL HASH实现的,根据访问地址中的HASH部分,唯一的确定一个子页面,并使用AJAX的方式将子页面中的内容拉取到主页面上的某个局部进行展示。

主页面的制作步骤:

  • 定义ng-app。
  • 定义子页面的显示区域 ui-view
  • 配置路由规则。
  • 完成控制器的制作。

子页面的制作步骤:

  • 绘制视图。
基本路由

主页面:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>基本路由主页面</title>
    <script src="https://cdn.bootcss.com/angular.js/1.6.3/angular.js"></script>
    <script src="https://cdn.bootcss.com/angular-ui-router/1.0.3/angular-ui-router.js"></script>
</head>
<body>
    <div ng-app="myApp">
        <a href="javascript:" ui-sref="a">路由1</a>
        <a href="javascript:" ui-sref="b">路由2</a>
        <div ui-view></div>
    </div>
    <script>
        //主页面:Controller层
        //注册app,提供路由配置"ui.router"
        var myApp = angular.module("myApp",["ui.router"]);
        //书写路由配置信息,需要至少$stateProvider,$urlRouterProvider
        myApp.config(function($stateProvider,$urlRouterProvider){
            //定义默认跳转,填写的是要默认跳转的路由的url
            $urlRouterProvider.otherwise("/route1");
            //其他路由跳转规则
            $stateProvider
                .state("a",{
                    url:"/route1",//地址栏显示的路径信息
                    templateUrl:"route1.html"//要跳转到视图的路径
                })
                .state("b",{
                    url:"/route2",//地址栏显示的路径信息
                    templateUrl:"route2.html",//要跳转到视图的路径
                    controller:"route2Ctrl",//在路由2中生效的Controller
                    controllerAs:"c2"//controller的别名
                });
        });
        myApp.controller("route2Ctrl",function(){
            this.test = "HelloWorld";
        })
    </script>
</body>
</html>

route1.html:

<div>这是路由1的页面</div>

route2.html:

<div>
    这是路由2的页面
    <div>
        {{c2.test}}
    </div>
</div>
样式控制

ui-sref-active 是一个根据当前路由子页面控制样式的属性,属性值是一个class。它可以被加在含有ui-sref属性的标签或者其父标签上。 当用户切换到对应的路由时,ui-sref-active所在的标签会被加入其属性值所对应的class 。

<div ng-app="myApp">
    <!--当前路由子页面为路由1时,这个a标签被加入名为active的class。-->
    <a ui-sref-active="active" href="javascript:" ui-sref="a">路由1</a>
    <!--当前路由子页面为路由2时,这个div标签被加入名为active的class。-->
    <div ui-sref-active="active"><a href="javascript:" ui-sref="b">路由2</a></div>
    <div ui-view></div>
</div>
动态路由(路由传参)

AngularJS中的路由传参是利用url传参,因此主要是在url相关部分进行配置。
动态路由配置步骤:

  • 在路由规则中的url部分使用/:指定参数的名字。 比如配置为url:"/user/:name/:age",那么当我们访问“/user/lins/18”时,“lins”就会被赋值到name中,18就会被赋值到age中。
  • 在ui-sref中进行参数传递。 语法:<a ui-sref="路由名称({参数1名:参数1,参数2名:参数2})" href="javascript:">链接文本</a>

下面的例子模拟了一个用户查询:在主页面将一个固定的用户id传递到user页面展示出来,在home页面(首页)将要查询用户的id传递到user页面展示出来。
主页面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/angular.js/1.6.3/angular.js"></script>
    <script src="https://cdn.bootcss.com/angular-ui-router/1.0.3/angular-ui-router.js"></script>
</head>
<body>
    <div ng-app="myApp">
        <a ui-sref="home" href="javascript:">首页</a>
        <!--固定参数传递:直接使用字符串形式-->
        <a ui-sref="user({id:'456'})" href="javascript:">用户</a>
        <div ui-view></div>
    </div>
    <script>
        myApp = angular.module("myApp",[ "ui.router"]);
        myApp.config(function($stateProvider,$urlRouterProvider){
            //定义默认跳转
            $urlRouterProvider.otherwise("home");
            //其他跳转规则
            $stateProvider
                .state("home",{
                    url:"/home",
                    templateUrl:"home.html",
                    controller:"HomeCtrl",
                    controllerAs:"hc"
                })
                .state("user",{
                    //配置该如何从中解析参数
                    //使用:参数名来匹配相应位置的参数
                    url:"/user/:id",
                    templateUrl:"user.html",
                    controller:"UserCtrl",
                    controllerAs:"uc"
                })
        });          
        myApp.controller("HomeCtrl",function(){

        });
        //子页面user中,需要向的controller中注入$stateParams服务,用于从地址中解析参数
        myApp.controller("UserCtrl",function($stateParams){
            this.id = $stateParams.id;
        });
    </script>
</body>
</html>

home页面:

<div>
    这是主页
    <input type="text" ng-model="hc.id">
    <!--动态参数传递:直接使用控制器的属性-->
    <a ui-sref="user({id:hc.id})" href="javascript:">
        <button type="button">查询</button>
    </a>
</div>

user页面:

<div>
    这是用户详情页
    <div>这是id为{{uc.id}}的用户的用户详情</div>
</div>

补充

多页面应用和单页面应用的详细对比

多页面应用

组成一个应用的每个页面,几乎是相互独立的。在加载每张页面时,仅仅加载这个页面所需的CSS和JS。
优点:

  • 进行首次页面加载时仅需加载这个页面所需资源,因此速度较快。
  • 因为页面是完整的从服务器传送到客户端,因此便于搜索引擎抓取。
  • 自动实现“前进”和“后退”的功能。

缺点:

  • 进行页面跳转时,整张页面从零开始加载,耗时较长。
  • WEB浏览器和手机APP需要两套不同的后端代码,不利于前后端分离。
单页面应用

整个应用仅有一个主页面。在加载主页面时,加载全部所需CSS和JS;在进行页面切换时,无需重新加载CSS和JS。
优点:

  • 在首次页面加载完成后,页面切换效率较高,有较好的用户体验。
  • WEB浏览器和手机APP需要的后段代码几乎完全相同,可以较好的实现前后端分离。

缺点:

  • 页面首次加载耗时较多,因此必须进行JS和CSS压缩来缓解。
  • 服务器到客户端的通信是不连续的,不利于搜索引擎抓取。
  • 需要利用URL HASH和页面栈等技术实现“前进”和“后退”的功能。
注:带**表示非重点

请叫我陈sir
26 声望3 粉丝

+∞的bug