104

一款优秀的前端框架——AngularJS - 一个柠檬

 6 years ago
source link: http://www.cnblogs.com/1996zy/p/7638101.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

一款优秀的前端框架——AngularJS

  前  言

        AngularJS是一款为了克服HTML在构建应用上的不足而设计的优秀的前端JS框架。AngularJS有着诸多特性,最为核心的是:MVC、模块化、自动化双向数据绑定、语义化标签、依赖注入等等。

        AngularJS 是一个 JavaScript 框架。它是一个以 JavaScript 编写的库。它可通过 <script> 标签添加到 HTML 页面。

     AngularJS 通过 指令 扩展了 HTML,且通过 表达式 绑定数据到 HTML。

  AngularJS 是以一个 JavaScript 文件形式发布的,可通过 script 标签添加到网页中。

  AngularJS最初是由MISKO Hevery和Adam Abrons于2009年开发。现在是由谷歌维护。它的最新版本是1.3.14。

    各个AngularJS版本下载:https://github.com/angular/angular.js/releases

   1.  走进 AngularJS

 AngularJS是为了克服HTML在构建应用上的不足而设计的。 AngularJS使得开发现代的单一页面应用程序(SPAs:Single Page Applications)变得更加容易。

  • AngularJS 把应用程序数据绑定到 HTML 元素。
  • AngularJS 可以克隆和重复 HTML 元素。
  • AngularJS 可以隐藏和显示 HTML 元素。
  • AngularJS 可以在 HTML 元素"背后"添加代码。
  • AngularJS 支持输入验证。
    2.  AngularJS 中的指令与表达式

    AngularJS 通过 指令 扩展了 HTML,且通过 表达式 绑定数据到 HTML。

2.1常用指令

AngularJS 指令是扩展的 HTML属性,带有前缀 ng-。
  1、ng-app=""声明AngularJS所管辖的区域。一般写在body或者html标签上,原则上一个页面只能有一个。

<body ng-app=""></body>

  2、ng-model 指令把元素值(比如输入域的值)绑定到应用程序的变量中。

    <input type="text" ng-model="name"/>

  3、 ng-bind把应用程序变量中的值,输出到页面HTML视图中,可以与表达式{{}}互相替换。

<p ng-bind="5+5+'Angular'"></p> 

  4、ng-init:初始化AngularJS应用程序中的变量值;

<body ng-app="" ng-init="name='NAME'">

  应用程序初始化时,name变量就附有初值。

2.2表达式

  AngularJS使用{{}}绑定表达式。用于将表达式的内容输出到页面中。
  表达式中可以是文字、运算符、变量等,也可以在表达式中进行运算输出结果。

 <p>{{5+5+"Angular"}}</p>                                   //结果为  10Angular

  如果AngularJS文件放在页面下方,在页面刷新的瞬间会看到{{}}表达式的原样,所以可以使用ng-bind指令代替表达式。

<p ng-bind="5+5+'Angular'"></p>
   3.  AngularJS中的MVC与作用域

3.1MVC三层架构

  1、Model(模型层):应用程序中用于处理数据的部分,(包括将数据保存或者修改到数据库、变量、文件中)。
     在AngularJS中,Model特指的是:应用程序中的各种数据。    

  2、View(视图层):用户可以看到的用户显示数据的页面。

  3、Controller(控制器):控制器是连接View和Model的桥梁,负责从View读取数据,接受用户的操作输入;并将数据发送给Model层。
    Model层对数据处理完毕后,将结果返回给Controller,Controller再将结果返回给View层显示。

3.2AngularJS中的模块化开发和依赖注入

3.2.1模块

创建一个angular的模块。即ng-app=""所需要绑定的部分。需要接受两个参数:
  ①模块名称。即ng-app双引号中需要绑定的名字。

<body ng-app="myapp">

  ②数组。表示需要注入的模块名称,不需要注入其他模块可用空数组代替。

var app=angular.module("myapp",[]);

  >>>Angular将常用的功能封装到Angular.js,创建主模块时直接可以使用,无需注入。
  >>> 而一些应用较少的功能,需要导入对应的JS文件,并且在[]中注入进这个模块,才能够使用。
  这就是AngularJS中的【模块化开发】与【依赖注入】!

3.2.2控制器

在AngularJS的模块上,创建一个控制器,需要传入两个参数:
  ①控制器名称:即ng-controller需要绑定的名称。

<div ng-controller="myCtrl">

  ②控制器的构造函数构造函数可以传入多个参数。
    >>>如果要在函数中要使用系统的内置对象,则必须通过函数的参数传入,否则不能使用。
    >>>AngularJS中的内置对象,都用开头,例如$scope,$rootScope        

3.3AngularJS中的作用域

  ① $scope局部作用域,声明在$scope上的属性和方法。只能在当前controller使用;
  ② $rootScope 根作用域。声明在$rootScope上的属性和方法,可以在整个ng-app所包含的范围使用。
  >>>如果没有使用$scope声明变量,而是直接使用ng-model在HTML标签中绑定的数据的作用域为:
  1、如果 ng-model写在某个controller中,则这个变量会默认绑定到当前的controller的$scope上。
  2、如果ng-model没有写在任何一个controller中,则这个变量会默认绑定到$rootScope 上。

>>>AngularJS中的父子作用域
  1、AngularJS中,子作用域只能访问父作用域中的变量,而不能修改父作用域的变量。
  2、为了解决上述问题,可以将父作用域中的变量声明为引用数据类型,例如对象等。
  这样可以在子作用域中,直接修改对象的属性,而不需要修改对象本身保存的地址。

<body ng-app="myApp">
        <input type="text" ng-model="age" placeholder="age" />
        
        <div ng-controller="myCtrl">
            <input type="text" ng-model="name" placeholder="name" />
            <div ng-bind="name+'-----myCtrl的name'"></div>
            <div ng-bind="age+'-----myCtrl的age'"></div>
        </div>
        
        <div ng-controller="myCtrl1">
            <div ng-bind="name+ '----myCtrl1的name'"></div>
            <div ng-bind="age+'-----myCtrl1的age'"></div>
            
            <input type="text" ng-model="test" />
            <input type="text" ng-model="obj.test" />
            <mark ng-bind="test+'myCtrl1-test'"></mark>
            <mark ng-bind="obj.test+'myCtrl1-obj.test'"></mark>
        </div>
        <mark ng-bind="test+'全局-test'"></mark>
        <mark ng-bind="obj.test+'全局-obj.test'"></mark>
        
        <div ng-bind="name + '----全局的name'"></div>
        <div ng-bind="age+'-----全局的age'"></div>
    </body>
<script type="text/javascript">
        var app = angular.module("myApp",[]);
        
        app.controller("myCtrl",function($scope,$rootScope){
            $scope.name = "zhangsan";
            $rootScope.age = "14";
        });
        
        app.controller("myCtrl1",function($rootScope){
            $rootScope.test = "aaa";
            $rootScope.obj = {
                test:'bbb'
            }
        });
 </script>
  4.AngularJS 中的过滤器

  过滤器可以使用一个管道字符(|)添加到表达式和指令中。

  >>> 系统内置的过滤器

        currency      将数字格式化为货币格式

        filter              从数组项中选择一个子集

        lowercase    格式化字符串为小写

        orderBy        根据某个表达式排列数组

         uppercase    格式化字符串为大写

    angular.module("app",[])
        .controller("ctrl",function($scope){
            $scope.classes=[
                {name:"张三",age:12,score:78},
                {name:"李四",age:12,score:66},
                {name:"王二麻子",age:12,score:98},
                {name:"赵六",age:12,score:54},
                {name:"李二狗",age:12,score:75},
            ]
        })
        /*
         * 自定义过滤器
         */
        .filter("showHello",function(){
            return function(text){
                return "Hello AngularJS";
            }
        })
        .filter("reverse",function(){
            return function(text){
                return text.split("").reverse().join("");
            }
        })
        /*
         * 自定义过滤器,同时需要传递过滤参数
         * 调用过滤器示例:<p>{{12345678901| hideTel:4}}</p>
         * 传入的参数4,将被过滤函数的num形参所接受
         */
        .filter("hideTel",function(){
            return function(text,num){
                num=num>0&&num<11?num:3;
                text=text+"";
                var newText=text.substring(0,11-num)
                          +text.substring(11-num,11).replace(/\d/g,"*");
                return newText;
            }
        })
        /*
         * 自定义过滤器,实现根据姓名筛选数据的功能。
         * >>> 调用示例:
         *             请输入姓名:<input type="text" ng-model="name"/>
         *        <tr ng-repeat="item in classes | filterByName:name">
         */
        .filter("filterByName",function(){
            return function(items,search){
                if(!search) return items;
                var arr=[];
                for (var i=0;i<items.length;i++) {
                    var index=items[i].name.indexOf(search);
                    if (index>-1) {
                        arr.push(items[i]);
                    }
                }
                return arr;
            }
        })
   5.AngularJS中的服务

5.1服务Service

  1、内置服务:
    >>>要使用服务,必须要把服务名通过controller的构造函数的参数注入进来!!!
    >>>系统内置的服务,统一使用$开头,服务中的属性和方法统一使用$$开头!!!自定义服务时,需注意与系统服务的写法区分开;
      $location:返回当前页面的URL地址信息,是一个对象;

var app = angular.module('myApp', []);
app.controller('customersCtrl', function($scope, $location) {
    $scope.myUrl = $location.absUrl();
});

      $http:向服务器发送请求,类似于JQuery中的Ajax;

var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http) {
    $http.get("welcome.htm").then(function (response) {
        $scope.myWelcome = response.data;
    });
});

      $timeout:相当于setTimeout()

var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $timeout) {
    $scope.myHeader = "Hello World!";
    $timeout(function () {
        $scope.myHeader = "How are you today?";
    }, 2000);
});

      $interval:相当于setInterval()

var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $interval) {
    $scope.theTime = new Date().toLocaleTimeString();
    $interval(function () {
        $scope.theTime = new Date().toLocaleTimeString();
    }, 1000);
});

  2、自定义服务

    接收两个参数:

              第一个参数是服务名
      第二个参数是自定义服务的构造函数。 我们自定义的服务,本质是一个对象。
    对象的属性 ,可以在构造函数中,使用this.属性 表示;
    对象的方法 ,可以在构造函数中,使用this.方法 表示;

.service("hexafy",function  () {
            this.gongneng="将十进制数转化为16进制";
            this.func=function (num) {
                return num.toString(16);
            }
        })

  使用过滤器实现同样功能:

.filter("filter1",function(){
            return function  (num) {
                return num.toString(16);
            }
        })

在过滤器中调用服务!!!
也必须在声明过滤器的外层构造函数中,注入服务名称!!!

.filter("filter2",function(hexafy,$location){
            return function  (num) {
                return hexafy.func(num);
            }
        })

5.2服务Factory

  factory服务在使用上与service服务没有太大差距。
  唯一的不同点,是声明服务时,factory服务是在函数中先声明好一个对象,然后使用return将对象返回。
  而service服务,则是直接在函数中使用this将属性和方法添加到对象上面。
        angular.module("app",[])
        .controller("ctrl",function  ($scope,hexafy) {
            $scope.gongneng=hexafy.gongneng;
            $scope.num1=hexafy.func(10);
        })
        .factory("hexafy",function  () {
            var obj={
                gongneng:"将十进制数转化为16进制",
                func:function (num) {
                return num.toString(16);
            }
          }
            return obj;
        })

5.3provider

  1、在AngularJs中,service服务 fantory服务都是基于provider服务实现的
  2、在定义provider时,可以使用this.$get方法,接受一个函数,函数里面采用与factory完全相同的写法

.provider("hexafy",function(){
            this.$get=function(){
                var obj={
                gongneng:"将十进制数转化为16进制",
                func:function(num){
                    return num.toString(16);
                }
            }
            return obj;
            }
        })

  3、在三种服务中,provider服务是唯一可以写进config配置阶段的服务。
    所以说,如果服务需要在配置阶段,也就是在声明controller之前执行的话,则可以使用provider,否则一般使用service或者factory。

angular.module("app",[])
        /*.config()表示配置阶段,在声明controller之前执行。可以用于声明一些在controller中
         * 需要使用的全局变量、方法、服务等
         */
        .config(function($provide){
            // 在配置阶段声明provider服务,需要在config中注入系统对象$provide
            $provide.provider("hexafy",function(){
                this.$get=function(){
                    var obj={
                        gongneng:"444"
                    }
                    return obj;
                }
            });
        })
        .controller("ctrl",function($scope,hexafy){
            $scope.gongneng=hexafy.gongneng;
        })
    6.  AngularJS 中的select与表格

  (一)使用数组作为数据源

    1、item表示数组中的每一项
    2、循环出的option中,value的值,默认为item
    3、option显示出的内容(<option></option>标签中的文字)是由item.site for决定的!

<select  ng-model="site"  ng-options="item.site for item in sites" >

  这种写法,默认生成的option效果如下:
  <option value="{site : "Google", url : "http://www.google.com"}">Google</option>

  <pre>{{site}}</pre>

  (二)以对象作为数据源
      1、(key,value)第一项表示对象的键,第二项表示对象的值;
    2、option的value,永远都是对象的值!
    3、option显示出的内容(<option></option>标签中的文字)是由...for决定的!也就是说,for前面是什么,option标签中就是什么。

       <select ng-model="site3" ng-options="key for (key,value) in sitess">
            <!--
                <option value="value">key/value(取决for前面的内容)</option>
            -->
        </select>

ng-options 和 ng-repeat
  1、ng-options使用时,是将指令添加在select上;
    ng-repeat使用时,是将指令添加在option上。   

2、ng-options使用时,必须同步给select标签绑定ng-model;
    ng-repeat使用时,不一定需要绑定ng-model;

3、ng-options使用时,我们只需要关心for前面的部分,即option标签中显示的文字;而option的value会自动分配,不由我们决定。
    (使用数组作为数据源时,value就是数组的每一项;使用对象作为数据源时,value永远都是对象的值)
    ng-repeat使用时,除了要指定option标签中显示的文字,
    还需要手动指定value中的内容,如果没有指定,则默认没有value;

  <tr ng-repeat="item in options">
                <!--
                    ng-repeat遍历是,$index 表示当前的行索引!
                -->
        <td>{{$index + 1}}</td>
        <td>{{item}}</td>
  </tr>
7.AngularJS中的DOM与事件

  1、ng-disabled="true/false";
传入true表示禁用,传入false表示可用

       <button ng-disabled="!myCheck">按钮</button>
        
        <label>
            <input type="checkbox" ng-model="myCheck" />是否同意!
        </label>
        <p>{{myCheck}}</p>            

  2、ng-show 是否显示

传入true表示显示,传入false表示隐藏

<label>
            <input type="checkbox" ng-model="myShow" />是否显示!
        </label>
        <p ng-show="myShow">我显示出来啦!!!</p>
        <hr />

   3、ng-hide 是否隐藏

<label>
            <input type="checkbox" ng-model="myHide" />是否隐藏!
        </label>
        <p ng-hide="myHide">我显示出来啦!!!</p>

  4、ng-if: 是否移除元素

当传入true显示,传入false时移除。
效果与ng-show相同,但是ng-show和ng-hide只是隐藏元素,而ng-if是将元素从DOM中直接移除!

<label>
            <input type="checkbox" ng-model="myIf" />是否移除!
        </label>
        <p ng-if="!myIf">移除!!!</p>

  5、ng-bind-html : 相当于 innerHTML
       而ng-bind 相当于 innerText
注意:要使用ng-bind-html,必须导入angular-sanitize.js文件进行安全验证。
同时需要在声明模块的时候,在数组中注入安全验证模块'ngSantize'

<div ng-bing-html="html"></div>

  6、ng-checked 设置复选框或单选框的选中状态。
  传入true设置当前复选框被选中。

<input type="checkbox" ng-model="all" /> Check all<br /><br />
        <input type="checkbox" ng-checked="all" /> 123<br />
        <input type="checkbox" ng-checked="all" /> 456<br />
        <input type="checkbox" ng-checked="all" /> 789<br />

  7、ng-class:用于设置给元素添加class类。
    可选值有以下几种情况:
  ① 可以是字符串。表示直接给元素添加对应的class。多个class之间,用空格分隔。
  ② 可以是对象。对象的键表示class名字,对象的值为true或false,当值为true时表示添加对应的class。
  ③ 可以是数组,数组中的值可以是字符串或对象,判断规则同上。

<div ng-class="'div div2'">这是一个div</div>
        <label>
            <input type="checkbox" ng-model="myClass" />给div添加样式?
        </label>
        <div ng-class="{'div':myClass,'div1':!myClass}">这是一个div</div>
        <div ng-class="[{'div':myClass,'div1':!myClass},'div3']">这是一个div</div>

  8、ng-switch 根据变量的值,选择不同的ng-switch-when来显示,当没有合适的选项时,显示ng-switch-default

8、AngularJS中的表单和输入验证

  1、表单中,常用的验证操作:
    $dirty 表单有填写记录
    $valid 字段内容合法的
    $invalid 字段内容是非法的
    $pristine 表单没有填写记录
    $error 表单验证不通过的错误信息

2、验证时,必须给form和input,设置name属性。
    给form和input设置name后,会自动将表单信息绑定到$scope作用域中。
    所以可以直接使用formName.inputName.$验证操作 得到验证结果。
  例如:
    formName.inputName.$dirty = "true"; 表示表单被填写过!
    formName.inputName.$invalid = "true"; 表示表单输入内容不合法!
    formName.inputName.$error.required = "true"; 表示设置了必填,但是没有输入!

注意:
    $error支持的验证:required/minlength/maxlength/partten/eamil/num/date/rul等

 3、为了避免AngularJS的验证与HTML5的表单验证冲突!!比如说 type="email" required等,H5也会进行验证,那么可以给form添加"novalidate"属性,禁用HTML5的验证功能。

<div class="container" style="width: 500px;margin: 50px auto;padding: 0px;">
        <div class="panel panel-primary">
            <div class="panel-heading">
                <div class="panel-title text-center">
                    用户注册
                </div>
            </div>
            <div class="panel-body">
                <form class="form-horizontal" name="form" novalidate>
                    <div class="row">
                        <div class="col-xs-3">用户名</div>
                        <div class="col-xs-9">
                            <input type="text"class="form-control"name="name"  ng-model="user.name" 
                            ng-minlength="6" ng-maxlength="12"/>
                            <p style="margin: 0px; color: red;" ng-show="form.name.$invalid && form.name.$dirty">
                                <span ng-show="form.name.$error.required">用户名必须填写</span>
                                <span ng-show="form.name.$error.minlength">用户名长度最小为6位</span>
                                <span ng-show="form.name.$error.maxlength">用户名长度最大为16位</span>
                            </p>
                        </div>
                    </div>
                    <div class="row">
                        <div class="col-xs-3">邮箱:</div>
                        <div class="col-xs-9">
                            <input type="email" class="form-control" name="email" ng-model="user.email" required/>
                            <p style="margin: 0px;color: red;" ng-show="form.email.$invalid && form.email.$dirty">
                                <span ng-show="form.email.$error.required">邮箱必须填写</span>
                                <span ng-show="form.email.$error.email">邮箱不合法</span>
                            </p>
                        </div>
                    </div>
                    <div class="row">
                        <div class="col-xs-3" >密码:</div>
                        <div class="col-xs-9">
                            <input type="password"class="form-control"name="pwd" ng-model="user.pwd"
                                pattern="^\w{6,18}$" required/>
                            <p style="margin: 0px; color: red;" ng-show="form.pwd.$invalid && form.pwd.$dirty">
                                <span ng-show="form.pwd.$error.pattern">密码只能由6-18位的字母、数字、下划线</span>
                            </p>
                        </div>
                    </div>
                    <div class="row">
                        <div class="col-xs-3" >确认密码:</div>
                        <div class="col-xs-9">
                            <input type="password"class="form-control" name="repwd" ng-model="user.repwd" required/>
                            <p style="margin: 0px; color: red;" ng-show="user.pwd!=user.repwd && form.repwd.$dirty">
                                两次密码输入不一致
                            </p>
                        </div>
                    </div>
                    <div class="row">
                        <div class="col-xs-5">
                            <input type="submit" value="注册" class="btn btn-success" ng-disabled="form.$invalid||user.pwd!=user.repwd"/>
                        </div>
                        <div class="col-xs-5">
                            <input type="reset" value="重置" class="btn btn-warning"/>
                        </div>
                    </div>
                </form>
            </div>
        </div>
    </div>
9.AngularJS中的动画

  在AngularJS中使用动画:
    1、导入angular-animate.js
    2、如果页面中没有自定义的app模块,则可以直接绑定系统模块ng-app="ngAnimate"
     如果页面中有自定义的app模块,则可以在自定义模块的数组中,注入ngAnimate。
     angular.module
  3、当使用ng-show、ng-hide显示或者隐藏元素的时候,系统会自动添加或者移除,ng-hide这个class类。
  4、当使用ng-if/ng-switch/ng-repeat等其他指令,需要分别设置显示后和隐藏后的两种class样式;
    显示后的class: .ng-enter-active,.ng-leave{}
    显示后的class: .ng-enter,.ng-leave-active{}


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK