angularjs_angularjs入门 - CSDN
精华内容
参与话题
  • Web前端学习笔记——AngularJS入门

    千次阅读 2018-09-14 20:37:48
    什么是 AngularJS 为什么使用 AngularJS AngularJS 的核心特性 相关链接 Angular 上手 安装 Angular 简单示例 案例解析 使用总结 Angular 基础概念 MVC 思想 模型 控制器   视图模型($scope) ...

    目录

    什么是 AngularJS

    为什么使用 AngularJS

    AngularJS 的核心特性

    相关链接

    Angular 上手

    安装 Angular

    简单示例

    案例解析

    使用总结

    Angular 基础概念

    MVC 思想

    模型

    控制器

     

    视图模型($scope)

    表达式(Expression)

    对比 JavaScript 表达式

    单向数据绑定

    双向数据绑定

    Angular 指令系统(Directive)

    指令属性小提示

    ng-app 指令

    ng-bind指令

    ng-bind-html指令

    ng-repeat 指令

    ng-class 指令

    ng-show/ng-hide 指令

     ng-cloak指令

    ng-link/ng-src 指令

     ng-switch指令

    其他常用指令

    自定义指令

    todomvc-app-template案例


    什么是 AngularJS

    • 一款非常优秀的前端高级 JS 框架
    • 最早由 Misko Hevery 等人创建
    • 2009 年被 Google 公式收购,用于其多款产品
    • 目前有一个全职的开发团队继续开发和维护这个库
    • 有了这一类框架就可以轻松构建 SPA 应用程序
    • 轻松构建 SPA(单一页面应用程序)
    • 单一页面应用程序:
      • 只有一个页面(整个应用的一个载体)
      • 内容全部是由AJAX方式呈现出啦的
    • 其核心就是通过指令扩展了 HTML,通过表达式绑定数据到 HTML。

    为什么使用 AngularJS

    • 更少的代码,实现更强劲的功能
    • 将一些以前在后台开发中使用的思想带入前端开发
    • 带领当前市面上的框架走向模式化或者架构化

    以前我们是这样的:

    以后将会是这样的:

    传统方式实现加法运算

    Angular实现加法运算

    传统方式实现数据列表呈现

    Angular实现数据列表呈现

    AngularJS 的核心特性

    • MVC
    • 模块化
    • 自动化双向数据绑定
    • 指令系统

    相关链接

    • http://www.apjs.net/
    • http://www.angularjs.cn/
    • http://docs.angularjs.cn/api
    • https://material.angularjs.org
    • http://angular-ui.github.io/

    Angular 上手

    安装 Angular

    • 下载 Angular.js 的包
      • https://github.com/angular/angular.js/releases
    • 使用 CDN 上的 Angular.js
      • http://apps.bdimg.com/libs/angular.js/1.4.9/angular.min.js
    • 使用 Bower 安装 bash bower install angular
    • 使用 NPM 安装 bash npm install angular
    • 每种方式安装包,本质都是将angular的库下载到当前文件夹中

    简单示例

    Hello world

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>第一个AngularJS示例</title>
    </head>
    
    <body>
      <div ng-app ng-init="name='zhangsan'">
        <p>在输入框中尝试输入:</p>
        <p>姓名:
          <input type="text" ng-model="name">
        </p>
        <p>{{name}}</p>
      </div>
      <script src="../bower_components/angular/angular.js"></script>
    </body>
    
    </html>
    

    案例解析

    • 当网页加载完毕,AngularJS 自动开始执行;
    • HTML 页面中 ng-xxx 的属性称之为指令(Directive);
    • ng-app 指令告诉 AngularJS,<div> 元素是 AngularJS 应用程序管理的边界;
    • ng-model 指令把文本框的值绑定到变量 name 上;
    • {{ name }} 表达式就是把应用程序变量 name 绑定到某个段落的 innerHTML。

    使用总结

    • Angular 最大程度的减少了页面上的 DOM 操作;
    • 让 JavaScript 中专注业务逻辑的代码;
    • 通过简单的指令结合页面结构与逻辑数据;
    • 通过自定义指令实现组件化编程;
    • 代码结构更合理;
    • 维护成本更低;
    • Angular 解放了传统 JavaScript 中频繁的 DOM 操作
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>Angular Hello world</title>
    </head>
    <!--
    所有需要ng管理的代码必须被包裹在一个有ng-app指令的元素中
    ng-app是ng的入口,表示当前元素的所有指令都会被angular管理(对每一个指令进行分析和操作)
    -->
    <body>
      <div ng-app ng-init="user.name='world'">
        <h1>使用NG实现双边数据绑定</h1>
        <input type="text"
          placeholder="请输入你的姓名"
          ng-model="user.name">
        <p>hello <strong>{{user.name}}</strong></p>
      </div>
      <script src="bower_components/angular/angular.js"></script>
    </body>
    
    </html>
    

     

    Angular 基础概念

    MVC 思想

    什么是 MVC 思想

    • MVC 是一种应用程序的开发思想,不是设计模式
    • 主要目的是为了解决应用程序展示结构,业务逻辑之间的紧耦合关系
    • 使应用程序的组成分为三个部件,每个部件有自己明确的职责,相互之间没有依赖
    • 将应用程序的组成划分为三个部分:Model View Controller
    • 控制器的作用就是初始化模型用的;
    • 模型就是用于存储数据的
    • 视图用于展现数据

    模型

    • AngularJS很重要的一个特性就是实现模块化编程,我们可以通过以下方式创建一个模块,对页面进行功能业务上的划分

    // 创建一个名字叫MyApp的模块,第二个参数指的是该模块依赖那些模块
    var myApp = angular.module("MyApp", []);
    
    • 也可以将重复使用的指令或过滤器之类的做成模块便于复用
    • 注意必须指定第二个参数,否则变成找到已经定义的模块
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>Angular 模块</title>
    </head>
    
    <body>
      <div ng-app="myApp" ng-controller="DemoController">
        <h1>使用NG实现双边数据绑定</h1>
        <input type="text" placeholder="请输入你的姓名" ng-model="user.name">
        <p>hello <strong>{{user.name}}</strong></p>
        <input type="button" ng-click="show()">
      </div>
      <script src="bower_components/angular/angular.js"></script>
      <script>
        // 注册模块 通过module函数,
        // 第一个参数是这个模块的名字
        // !!! 第二个参数是这个模块所依赖的模块, 如果不依赖任何模块也必须传递第二个参数,如果没有传递第二个参数,angular.module就不是创建一个模块
        // angular.module 返回 刚刚创建的模块对象
       var app=  angular.module('myApp',[]);
        // app.controller 方法用于创建一个控制器,所创建的控制器属于myApp模块
        // app.controller('DemoCtrl');
        // 控制器函数的参数中有一个$scope
        // angular.module('myApp').controller('DemoController', function($scope) {
        //   // 当控制器执行时会自动执行的函数
        //   $scope.user = {};
        //   $scope.user.name = '张三';
        //   // $scope不仅仅可以往视图中暴露数据,还可以暴露行为
        //   $scope.show = function() {
        //     console.log($scope.user);
        //   };
        // });
      </script>
    </body>
    
    </html>
    

    控制器

    • 调度逻辑的集合

    angular.module('OneApp', [])
        .controller('HelloController', [
            '$scope',
            function($scope) {
                $scope.p = {
                    name: 'zhangsan'
                };
            }
        ]);
    
    • 控制器的三种主要职责:
    1. –为应用中的模型设置初始状态
    2. –通过$scope对象把数据模型或函数行为暴露给视图
    3. –监视模型的变化,做出相应的动作
    // 监视购物车内容变化,计算最新结果
    $scope.$watch(‘totalCart’, calculateDiscount);
    
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>Angular Controller</title>
    </head>
    
    <body ng-app="myModule" ng-controller="HelloController">
      <script src="bower_components/angular/angular.js"></script>
      <script>
        // 由于控制器是必须出现在某个模块下的,想创建一个控制器必须先创建模块
        var module = angular.module('myModule', []); // 返回的就是模块对象
    
        // angular在执行控制器函数时,
        // 会根据参数的名字($scope)去自动的注入对象
        // 根据参数名称传递对应对象,所以必须要写正确的参数名称
        // module.controller('HelloController', function($scope) {
        //   console.log($scope);
        // });
        //
        // 由于压缩代码会改变参数名称,注册控制的标准方式就是通过第二个参数传递数组的方式(数组的成员最后一个就是原本的控制器函数,前面的成员都是需要注入的对象名称)
        module.controller('HelloController', ['$scope','$http', function(a,b) {
          console.log(a);
        }]);
      </script>
    </body>
    
    </html>
    
    <!DOCTYPE html>
    <html lang="en" ng-app="HelloApp">
    
    <head>
      <meta charset="utf-8">
    </head>
    
    <body>
      <table border="1" ng-controller="WorldController">
        <tr>
          <td>用户名</td>
          <td>
            <input type="text" ng-model="user.username">
          </td>
        </tr>
        <tr>
          <td>密码</td>
          <td>
            <input type="password" ng-model="user.password">
          </td>
        </tr>
        <tr>
          <td></td>
          <td>
            <input type="button" ng-click="login()" value="登陆">
          </td>
        </tr>
        <tr>
          <td></td>
          <td>{{message}}</td>
        </tr>
      </table>
      <script src="bower_components/angular/angular.js"></script>
      <script>
        // 创建一个模块
        var app = angular.module('HelloApp', []);
        // 为这个模块创建一个控制器
        app.controller('WorldController', ['$scope', function($scope) {
    
          // 数据
          $scope.user = {
            username: '',
            password: ''
          };
          $scope.demo = '';
    
          // 行为数据
          $scope.login = function() {
            // 因为数据的变化时双向的同步,所以界面上的值变化会同步到$scope.user上
            console.log($scope.user);
          };
    
    
          // 请输入用户名  输入格式不合法
          $scope.message = '请输入用户名';
          // $scope.message取决于$scope.user
    
          // 官方的API中提供了一个$scope.$watch方法,
          $scope.$watch('user.username', function(now, old) {
            // 当user.username发生变化时触发这个函数
            // console.log('now is ' + now);
            // console.log('old is ' + old);
            if (now) {
              if (now.length < 7) {
                $scope.message = '输入格式不合法';
              } else {
                $scope.message = '';
              }
            } else {
              $scope.message = '请输入用户名';
            }
          });
    
          // angular 基本不用操作DOM,如果必要,可以使用angular提供的jqlite
          //
          // angular.element('body')
        }]);
      </script>
    </body>
    
    </html>
    

     

    视图模型($scope)

    • 视图和控制器之间的桥梁
    • 用于在视图和控制器之间传递数据
    • 利用$scope暴露数据模型(数据,行为)

    表达式(Expression)

    • 作用:
    1. –使用 表达式 把数据绑定到 HTML。
    • 语法:
    1. –表达式写在双大括号内:{{ expression }}
    • 比较:
    1. –表达式作用类似于ng-bind指令
    2. –建议更多的使用指令
    • AngularJS表达式很像JavaScript表达式
    • 它们可以包含文字、运算符和变量
    • 如 {{ 5 + 5 }} 或 {{ firstName + ‘-’ + lastName }}
    • 数字  {{ 100 + 100 }}
    • 字符串  {{ 'hello' + 'angular' }}
    • 对象  {{ zhangsan.name }}
    • 数组  {{ students[10] }}
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>Angular 表达式</title>
      <style>
        /* ng-cloak指令就是在NG执行完毕过后自动移除 */
    
        [ng-cloak],
        .ng-cloak {
          display: none;
        }
      </style>
    </head>
    
    <body ng-app class="ng-cloak">
      {{ true ? 'true':'false' }}
      <script src="bower_components/angular/angular.js"></script>
    </body>
    
    </html>
    

    对比 JavaScript 表达式

    • 相同点:
    1. –AngularJS 表达式可以包含字母,操作符,变量。
    • 不同点:
    1. –AngularJS 表达式可以写在 HTML 中。
    2. –AngularJS 表达式不支持条件判断,循环及异常。
    3. –AngularJS 表达式支持过滤器。

    单向数据绑定

    •模型变化过后,自动同步到界面上;

    •一般纯展示型的数据会用到单项数据绑定;

    •使用表达式的方式都是单向的

    双向数据绑定

    •两个方向的数据自动同步:

    •模型发生变化自动同步到视图上;

    •视图上的数据发生变化过后自动同步到模型上;

    Angular 指令系统(Directive)

    • AngularJS 有一套完整的、可扩展的、用来帮助 Web 应用开发的指令集
    • 在 DOM 编译期间,和 HTML 关联着的指令会被检测到,并且被执行
    • 在 AngularJS 中将前缀为 ng- 这种属性称之为指令,其作用就是为 DOM 元素调用方法、定义行为绑定数据等
    • 简单说:当一个 Angular 应用启动,Angular 就会遍历 DOM 树来解析 HTML,根据指令不同,完成不同操作

    指令属性小提示

    • HTML5 允许扩展的(自制的)属性,以 data- 开头。
    • AngularJS 属性以 ng- 开头,但是您可以使用 data-ng- 来让网页对 HTML5 有效。
    • 二者效果相同。

    ng-app 指令

    • ng-app指令用来标明一个AngularJS应用程序
    • 标记在一个AngularJS的作用范围的根对象上
    • 系统执行时会自动的执行根对象范围内的其他指令
    • 可以在同一个页面创建多个ng-app节点
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>ng-app 指令</title>
    </head>
    
    <body>
      <!-- angular找到第一个ng-app过后就不会再找 -->
      <div ng-app="myApp1" ng-controller="App1Controller">
        <input type="button" value="按钮1" ng-click="do1()">
      </div>
      <div ng-app="myApp2" ng-controller="App2Controller">
        <input type="button" value="按钮2" ng-click="do2()">
      </div>
      <script src="bower_components/angular/angular.js"></script>
      <script>
        /**
         * myApp1 Module
         *
         * Description
         */
        var myApp1 = angular.module('myApp1', []);
        myApp1.controller('App1Controller', ['$scope', function($scope) {
          $scope.do1 = function() {
            console.log(11111);
          };
        }]);
    
        var myApp2 = angular.module('myApp2', []);
        myApp2.controller('App2Controller', ['$scope', function($scope) {
          $scope.do2 = function() {
            console.log(22222);
          };
        }]);
        // 手动的让第二个div被myApp2管理
        angular.bootstrap(document.querySelector('[ng-app="myApp2"]'),['myApp2']);
      </script>
    </body>
    
    </html>
    

     

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>ng-app 指令</title>
    </head>
    
    <body ng-app="myApp">
      <!-- angular找到第一个ng-app过后就不会再找 -->
      <div ng-controller="App1Controller">
        <input type="button" value="按钮1" ng-click="do1()">
      </div>
      <div ng-controller="App2Controller">
        <input type="button" value="按钮2" ng-click="do2()">
      </div>
      <script src="bower_components/angular/angular.js"></script>
      <script>
        // 零件1
        var myApp1 = angular.module('myApp1', []);
        myApp1.controller('App1Controller', ['$scope', function($scope) {
          $scope.do1 = function() {
            console.log(11111);
          };
        }]);
        // 零件2
        var myApp2 = angular.module('myApp2', []);
        myApp2.controller('App2Controller', ['$scope', function($scope) {
          $scope.do2 = function() {
            console.log(22222);
          };
        }]);
    
        /**
         * myApp Module
         *
         * Description
         */
        angular.module('myApp', ['myApp1', 'myApp2']);
      </script>
    </body>
    
    </html>
    

    ng-bind指令

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>ng-bind 指令</title>
    </head>
    <body ng-app ng-init="username='<h1>shit</h1>'">
      <!-- <strong>{{username}}</strong> -->
      <!-- ng-bind指令在绑定的值包含HTML时会转义,为了安全(跨站脚本攻击) -->
      <strong ng-bind="username"></strong>
      <script src="bower_components/angular/angular.js"></script>
    </body>
    </html>

    ng-bind-html指令

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>ng-bind-html 指令</title>
    </head>
    
    <body ng-app="myApp" ng-init="username='<h1>shit</h1>'">
      <!-- <strong>{{username}}</strong> -->
      <!-- ng-bind指令在绑定的值包含HTML时会转义,为了安全(跨站脚本攻击) -->
      <strong ng-bind-html="username"></strong>
      <script src="bower_components/angular/angular.js"></script>
      <script src="bower_components/angular-sanitize/angular-sanitize.js"></script>
      <script>
        // 使用自定义的模块才可以依赖别的包里面定义模块,angular定义的默认模块没有依赖任何
        angular.module('myApp', ['ngSanitize']);
      </script>
    </body>
    
    </html>
    

    ng-repeat 指令

    • ng-repeat指令用来编译一个数组重复创建当前元素,如
    <ul class="messages">
        <li ng-repeat="item in messages track by $index">
            {{item}}
        </li>
    </ul>
    

     

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>ng-repeat 指令</title>
    </head>
    
    <body ng-app="myApp">
    
    <ul ng-controller="ListController">
      <!-- ng-repeat 会遍历数组中每一个元素,分别创建li -->
      <li ng-repeat="item in xiaoheishenghuo" data-id="{{item.id}}">
        <span>{{$first?'开始':''}}</span>
        <strong>{{item.name}}</strong>
        &nbsp;&nbsp;&nbsp;&nbsp;
        <span>{{item.age}}</span>
        <span>{{$last?'没有了':''}}</span>
      </li>
    </ul>
    
      <script src="bower_components/angular/angular.js"></script>
      <script>
        angular.module('myApp', [])
          .controller('ListController', ['$scope', function($scope) {
    
    
            $scope.xiaoheishenghuo = [];
    
            for (var i = 1; i < 10; i++) {
              $scope.xiaoheishenghuo[$scope.xiaoheishenghuo.length] = {
                id: i,
                name: '赵小黑的小' + i,
                age: 20 + i
              };
            }
    
    
          }]);
      </script>
    </body>
    
    </html>
    

    ng-class 指令

    • ng-class指令可以设置一个键值对,用于决定是否添加一个特定的类名,键为class名,值为bool类型表示是否添加该类名
    <ul class="messages">
        <li ng-repeat="item in messages track by $index" ng-class="{red:item.read}">
            {{item.content}}
        </li>
    </ul>
    

     

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>ng-repeat 指令</title>
      <style>
        .red {
          color: red;
        }
    
        .green {
          color: green;
        }
      </style>
    </head>
    
    <body ng-app="myApp">
      <ul ng-controller="ListController">
        <!-- class="{{$even?'red':'green'}}" -->
        <!-- ng-class会根据当前设置对象的属性和属性值决定是否添加特定类名 -->
        <li ng-repeat="item in xiaoheishenghuo" ng-class="{red:$even,green:$odd}" data-id="{{item.id}}">
          <strong>{{item.name}}</strong> &nbsp;&nbsp;&nbsp;&nbsp;
          <span>{{item.age}}</span>
        </li>
      </ul>
      <script src="bower_components/angular/angular.js"></script>
      <script>
        angular.module('myApp', [])
          .controller('ListController', ['$scope', function($scope) {
    
    
            $scope.xiaoheishenghuo = [];
    
            for (var i = 1; i < 10; i++) {
              $scope.xiaoheishenghuo[$scope.xiaoheishenghuo.length] = {
                id: i,
                name: '赵小黑的小' + i,
                age: 20 + i
              };
            }
    
    
          }]);
      </script>
    </body>
    
    </html>
    
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>ng-repeat 指令</title>
      <style>
        .red {
          background-color: red;
        }
    
        .green {
          background-color: green;
        }
    
        #box {
          height: 200px;
          width: 200px;
          transition:background-color 1s ease;
        }
      </style>
    </head>
    
    <body ng-app>
      <select ng-model="style">
        <option value="red">红色</option>
        <option value="green">绿色</option>
      </select>
      <!-- <div id="box" ng-class="style"></div> -->
      <div id="box" ng-class="{red:style=='red', green:style=='green'}"></div>
      <script src="bower_components/angular/angular.js"></script>
    </body>
    
    </html>
    

     

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>ng-repeat 指令</title>
      <style>
        .red {
          color: red;
        }
    
        .green {
          color: green;
        }
      </style>
    </head>
    
    <body ng-app="myApp">
      <input type="text" ng-model="lastname">
      <ul ng-controller="ListController">
        <li ng-repeat="name in students track by $id($index)" ng-class="{red:lastname!=''&&name.startsWith(lastname)}">{{name}}</li>
      </ul>
      <script src="bower_components/angular/angular.js"></script>
      <script>
        angular.module('myApp', [])
          .controller('ListController', ['$scope', function($scope) {
    
    
            $scope.students = ['胡shit', '赵四', '网商务', '李三', '李三', '李三'];
    
    
          }]);
      </script>
    </body>
    
    </html>
    

    ng-show/ng-hide 指令

    • ng-show/ng-hide指令会根据属性值去确定是否展示当前元素,例如ng-show=false则不会展示该元素
    <ul class="messages">
        <li ng-repeat="item in messages track by $index" ng-show="item.read">
            {{item.content}}
        </li>
    </ul>
    
    <!DOCTYPE html>
    <html lang="en" ng-app="myApp">
    
    <head>
      <meta charset="UTF-8">
      <title>ng-class 指令</title>
      <style>
        .tips {
          position: absolute;
          top: 0;
          left: 0;
          right: 0;
          bottom: 0;
          background-color: rgba(100, 100, 100, .5);
          font-size: 40px;
          line-height: 100vh;
          text-align: center;
        }
      </style>
    </head>
    
    <body ng-controller="ListController">
      <div>
        aaaaaaaaaaaaaa
      </div>
      <!-- ng-show 决定是否显示 ng-hide 是否隐藏 ng-if 是否存在 -->
      <div class="tips" ng-if="loading">
        loading...
      </div>
      <script src="bower_components/angular/angular.js"></script>
      <script>
        angular.module('myApp', [])
          .controller('ListController', ['$scope', '$timeout', function($scope, $timeout) {
            $scope.loading = true;
    
            $timeout(function() {
              $scope.loading = false;
    
              $timeout(function() {
                $scope.loading = true;
              }, 3000);
    
            }, 3000);
          }]);
      </script>
    </body>
    
    </html>
    

     

     ng-cloak指令

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>ng-cloak 指令</title>
      <!-- <style>
        [ng\:cloak],
        [ng-cloak],
        [data-ng-cloak],
        [x-ng-cloak],
        .ng-cloak,
        .x-ng-cloak,
        .ng-hide:not(.ng-hide-animate) {
          display: none !important;
        }
    
        ng\:form {
          display: block;
        }
    
        .ng-animate-shim {
          visibility: hidden;
        }
    
        .ng-anchor {
          position: absolute;
        }
      </style> -->
      <script src="bower_components/angular/angular.js"></script>
    </head>
    
    <body ng-app ng-cloak>
      <span>{{'hello angular'}}</span>
    </body>
    
    </html>
    
    • ng-if是指是否存在DOM元素

    ng-link/ng-src 指令

    • ng-link/ng-src指令用于解决当链接类型的数据绑定时造成的加载BUG,如
    <!-- 浏览器在解析HTML时会去请求{{item.url}}文件 -->
    <img src="{{item.url}}">
    <!-- 可以使用ng-src解决该问题 -->
    <img ng-src="{{item.url}}">
    
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>ng-src</title>
      <script src="bower_components/angular/angular.js"></script>
    </head>
    
    <body ng-app ng-init="imgUrl='22.png'" ng-cloak>
      <img ng-src="{{imgUrl}}" alt="">
    
      <a ng-href="{{imgUrl}}">跳转到图片</a>
    </body>
    
    </html>
    

     ng-switch指令

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>ng-switch 指令</title>
    </head>
    <body ng-app>
      <select ng-model="selected">
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
      </select>
      <div ng-switch="selected">
        <div ng-switch-when="1">
          你选择的是1
        </div>
        <div ng-switch-when="2">
          你选择的是2
        </div>
        <div ng-switch-when="3">
          你选择的是3
        </div>
        <div ng-switch-default>
          你什么都没选
        </div>
      </div>
    
      <script src="bower_components/angular/angular.js"></script>
    </body>
    </html>

    其他常用指令

    • ng-model
    • ng-class
    • ng-show/ng-hide/ng-if
    • ng-click
    • ng-link/ng-src
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>ng-xxx 其他指令</title>
    </head>
    
    <body ng-app>
      <p>
        <input type="checkbox" ng-model="checked">全选/取消全选</p>
      <ul>
        <!-- ng-checked 和 ng-selected 只会做数据到视图的同步,不会做视图到数据的同步 -->
        <li>选项01
          <input type="checkbox" ng-checked="checked">
        </li>
        <li>选项02
          <input type="checkbox" ng-checked="checked">
        </li>
        <li>选项03
          <input type="checkbox" ng-checked="checked">
        </li>
        <li>选项04
          <input type="checkbox" ng-checked="checked">
        </li>
        <li>选项05
          <input type="checkbox" ng-checked="checked">
        </li>
      </ul>
      <script src="bower_components/angular/angular.js"></script>
    </body>
    
    </html>
    

    自定义指令

    • AngularJS中可以通过代码自定义指令:
    myModule.directive('hello', function() {
        return {
            restrict: 'E',
            template: '<h1>Hello world</h1>',
            replace: true
        };
    });
    myApp.directive("ngHover", function() {
        return function(scope, element, attrs) {
            element.bind("mouseenter", function() {
                element.css("background", "yellow");
            });
            element.bind("mouseleave", function() {
                element.css("background", "none");
            });
        }
    });
    
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>Document</title>
      <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css">
    </head>
    
    <body ng-app="demoApp">
      <!-- <itcastButton></itcastButton> -->
      <!-- <itcast-button></itcast-button> -->
      <!-- <div itcastButton></div> -->
      <btn-primary></btn-primary>
      <btn-danger></btn-danger>
      <script src="bower_components/angular/angular.js"></script>
      <script>a
        var demoApp = angular.module('demoApp', []);
    
        // 第一个参数是指令的名字,第二个参数任然应该使用一个数组,数组的最后一个元素是一个函数
        // 定义指令的名字,应该使用驼峰命名法
        demoApp.directive('itcastButton', [function() {
          // 该函数应该返回一个指令对象
          return {
            template:'<input type="button" value="itcast" class="btn btn-lg btn-primary btn-block" />'
          };
        }]);
    
    
        // demoApp.directive('btnPrimary', [function() {
        //   return {
        //     template:'<input type="button" value="itcast" class="btn btn-primary" />'
        //   };
        // }]);
    
        // demoApp.directive('btnDanger', [function() {
        //   return {
        //     template:'<input type="button" value="itcast" class="btn btn-danger" />'
        //   };
        // }]);
    
        // demoApp.directive('btnSuccess', [function() {
        //   return {
        //     template:'<input type="button" value="itcast" class="btn btn-success" />'
        //   };
        // }]);
    
        demoApp.controller('DemoController', ['$scope', function($scope) {
          // $scope.xxxx=xxx;
          // $scope.do=function() {
    
          // };
          // $scope.$watch('',function(now,old) {
    
          // });
        }]);
      </script>
    </body>
    
    </html>
    
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>Document</title>
      <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css">
    </head>
    
    <body ng-app="demoApp">
      <!-- <btn>itcast</btn> -->
      <div breadcrumb></div>
      <breadcrumb data=""></breadcrumb>
      <script src="bower_components/angular/angular.js"></script>
      <script>
        var demoApp = angular.module('demoApp', []);
    
    
        demoApp.directive('breadcrumb', [function() {
          // Runs during compile
          return {
            // 指定当前指令的类型什么样的
            // restrict: 'EA',
            // // E = Element, A = Attribute, C = Class, M = Comment
            // template: '', // 模版字符串
            templateUrl: 'tmpls/breadcrumb.html',
            replace: true,
            // transclude: true,
          };
        }]);
    
        // demoApp.directive('btn', [function() {
        //   return{
        //     scope:{
        //       primary:'@',
        //       lg:'@',
        //       block:'@',
        //     },
        //     template:'<button class="btn {{primary==\'true\'?\'btn-primary\':\'\'}}">button</button>'
        //   }
        // }]);
    
        // demoApp.directive('btn', [function() {
        //   return {
        //     // 指令对象的transclude必须设置为true才可以在模版中使用ng-transclude指令
        //     transclude: true,
        //     replace: true, // 替换指令在HTML中绑定的元素
        //     template: '<button class="btn btn-primary btn-lg" ng-transclude></button>'
        //   };
        // }]);
      </script>
    </body>
    
    </html>
    
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>封装一个面包屑导航</title>
      <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css">
    </head>
    
    <body ng-app="myApp" ng-controller="DemoController">
      <breadcrumb data="{{pathData1}}"></breadcrumb>
      <breadcrumb data="{{pathData2}}"></breadcrumb>
      <script src="bower_components/angular/angular.js"></script>
      <script>
        var myApp = angular.module('myApp', []);
    
        myApp.controller('DemoController', ['$scope', function($scope) {
          $scope.pathData1 = {
            home: '#',
            itcast: '#',
            itheima: '#',
            bbs: '#'
          };
          $scope.pathData2 = {
            home: '#',
            library: '#',
            data: '#'
          };
        }]);
    
        // 定义一个面包屑导航指令
        myApp.directive('breadcrumb', [function() {
          // 返回指令对象
          return {
            scope: {},
            templateUrl: 'tmpls/breadcrumb.html',
            replace: true,
            link: function(scope, element, attributes) {
              scope.data = JSON.parse(attributes.data);
              // console.log(scope.data);
            }
          };
        }]);
      </script>
    </body>
    
    </html>
    

    todomvc-app-template案例

    <!doctype html>
    <html lang="en">
    	<head>
    		<meta charset="utf-8">
    		<meta name="viewport" content="width=device-width, initial-scale=1">
    		<title>Template • TodoMVC</title>
    		<link rel="stylesheet" href="node_modules/todomvc-app-css/index.css">
    		<!-- CSS overrides - remove if you don't need it -->
    		<link rel="stylesheet" href="css/app.css">
    	</head>
    	<body ng-app="MyTodoMvc">
    		<section class="todoapp" ng-controller="MainController">
    			<header class="header">
    				<h1>todos</h1>
    				<form ng-submit="add()">
    					<input class="new-todo" placeholder="What needs to be done?" ng-model="text" autofocus>
    				</form>
    			</header>
    			<section class="main">
    				<input class="toggle-all" type="checkbox" ng-click="toggleAll()">
    				<label for="toggle-all">Mark all as complete</label>
    				<ul class="todo-list">
    					<li ng-repeat="todo in todos" ng-class="{completed:todo.completed,editing:todo.id===currentEditingId}" data-id="{{todo.id}}">
    						<div class="view">
    							<input class="toggle" type="checkbox" ng-model="todo.completed">
    							<label ng-dblclick="editing(todo.id)">{{todo.text}}</label>
    							<button class="destroy" ng-click="remove(todo.id)"></button>
    						</div>
    						<form ng-submit="save()">
    							<input class="edit" ng-model="todo.text" ng-blur="save()">
    						</form>
    					</li>
    				</ul>
    			</section>
    			<!-- This footer should hidden by default and shown when there are todos -->
    			<footer class="footer">
    				<!-- This should be `0 items left` by default -->
    				<span class="todo-count"><strong>{{todos.length}}</strong> item left</span>
    				<!-- Remove this if you don't implement routing -->
    				<ul class="filters">
    					<li>
    						<a class="selected" href="#/">All</a>
    					</li>
    					<li>
    						<a href="#/active">Active</a>
    					</li>
    					<li>
    						<a href="#/completed">Completed</a>
    					</li>
    				</ul>
    				<!-- Hidden if no completed items are left ↓ -->
    				<button class="clear-completed" ng-click="clear()" ng-show="existCompleted()">Clear completed</button>
    			</footer>
    		</section>
    		<footer class="info">
    			<p>Double-click to edit a todo</p>
    			<!-- Remove the below line ↓ -->
    			<p>Template by <a href="http://sindresorhus.com">Sindre Sorhus</a></p>
    			<!-- Change this out with your name and url ↓ -->
    			<p>Created by <a href="http://todomvc.com">you</a></p>
    			<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
    		</footer>
    		<!-- Scripts here. Don't remove ↓ -->
    		<script src="node_modules/angular/angular.js"></script>
    		<script src="js/app.js"></script>
    	</body>
    </html>
    
    <--!app.js-->
    (function(angular) {
      'use strict';
    
      /**
       * MyTodoMvc Module
       *
       * 应用程序的主要的模块
       */
      var myApp = angular.module('MyTodoMvc', []);
    
      // 注册一个主要的控制器
      myApp.controller('MainController', ['$scope', function($scope) {
        // [1,2,3,4,5]
        function getId() {
          var id = Math.random(); // 1 2
          for (var i = 0; i < $scope.todos.length; i++) {
            if ($scope.todos[i].id === id) {
              id = getId();
              break;
            }
          }
          return id;
        }
    
        // 文本框需要一个模型
        $scope.text = '';
    
        // 任务列表也需要一个
        // 每一个任务的结构 { id: 1, text: '学习', completed: true }
        $scope.todos = [{
          id: 0.123,
          text: '学习',
          completed: false
        }, {
          id: 0.22,
          text: '睡觉',
          completed: false
        }, {
          id: 0.232,
          text: '打豆豆',
          completed: true
        }, ];
    
        // 添加todo
        $scope.add = function() {
        	if(!$scope.text){
        		return;
        	}
          $scope.todos.push({
            // 自动增长?
            id: getId(),
            // 由于$scope.text是双向绑定的,add同时肯定可以同他拿到界面上的输入
            text: $scope.text,
            completed: false
          });
          // 清空文本框
          $scope.text = '';
        };
    
    
        // 处理删除
        $scope.remove = function(id) {
          // 删除谁
          for (var i = 0; i < $scope.todos.length; i++) {
            if ($scope.todos[i].id === id) {
              $scope.todos.splice(i, 1);
              break;
            }
          }
          // $scope.todos
        };
    
        // 清空已完成
        $scope.clear = function() {
          var result = [];
          for (var i = 0; i < $scope.todos.length; i++) {
            if (!$scope.todos[i].completed) {
              result.push($scope.todos[i]);
            }
          }
          $scope.todos = result;
        };
    
        // 是否有已经完成的
        $scope.existCompleted = function() {
          // 该函数一定要有返回值
          for (var i = 0; i < $scope.todos.length; i++) {
            if ($scope.todos[i].completed) {
              return true;
            }
          }
          return false;
        };
    
        // 当前编辑哪个元素
        $scope.currentEditingId = -1;
        $scope.editing = function(id) {
          $scope.currentEditingId = id;
        };
        $scope.save = function() {
          $scope.currentEditingId = -1;
        };
    
        // $scope.checkall = false;
        // $scope.$watch('checkall', function(now, old) {
        //   for (var i = 0; i < $scope.todos.length; i++) {
        //     $scope.todos[i].completed = now;
        //   }
        // });
    
        var now = true;
        $scope.toggleAll = function() {
          for (var i = 0; i < $scope.todos.length; i++) {
            $scope.todos[i].completed = now;
          }
          now = !now;
        }
    
      }]);
    
    })(angular);
    

     

    展开全文
  • angularJS详解

    2019-11-07 18:48:51
    这篇文章转载 kooky798 的博客,http://blog.csdn.net/yy374864125/article/details/41349417, 写到这么详细也是没谁了,必须粉一个 ...

    这篇文章转载  kooky798 的博客,http://blog.csdn.net/yy374864125/article/details/41349417,

    写到这么详细也是没谁了,必须粉一个

     

     

    1 前言

    前端技术的发展是如此之快,各种优秀技术、优秀框架的出现简直让人目不暇接,紧跟时代潮流,学习掌握新知识自然是不敢怠慢。

    AngularJS是google在维护,其在国外已经十分火热,可是国内的使用情况却有不小的差距,参考文献/网络文章也很匮乏。这里便将我学习AngularJS写成文档,一方面作为自己学习路程上的记录,另一方面也给有兴趣的同学一些参考。

    首先我自己也是一名学习者,会以学习者的角度来整理我的行文思路,这里可能只是些探索,有理解或是技术上的错误还请大家指出;其次我特别喜欢编写小例子来把一件事情说明白,故在文中会尽可能多的用示例加代码讲解,我相信这会是一种比较好的方式;最后,我深知AngularJS的使用方式跟jquery的使用方式有很大不同,在大家都有jquery、ext经验的条件下对于angular的学习会困难重重,不过我更相信在大家的坚持下,能够快速的学好AngularJS,至少咱也能深入了解到AngularJS的基本思想,对咱们以后自己的插件开发、项目开发都会有很大的启示。


    2 AngularJS概述


    2.1 AngularJS是什么?

    AngularJs(后面就简称ng了)是一个用于设计动态web应用的结构框架。首先,它是一个框架,不是类库,是像EXT一样提供一整套方案用于设计web应用。它不仅仅是一个javascript框架,因为它的核心其实是对HTML标签的增强。

    何为HTML标签增强?其实就是使你能够用标签完成一部分页面逻辑,具体方式就是通过自定义标签、自定义属性等,这些HTML原生没有的标签/属性在ng中有一个名字:指令(directive)。后面会详细介绍。那么,什么又是动态web应用呢?与传统web系统相区别,web应用能为用户提供丰富的操作,能够随用户操作不断更新视图而不进行url跳转。ng官方也声明它更适用于开发CRUD应用,即数据操作比较多的应用,而非是游戏或图像处理类应用。

    为了实现这些,ng引入了一些非常棒的特性,包括模板机制、数据绑定、模块、指令、依赖注入、路由。通过数据与模板的绑定,能够让我们摆脱繁琐的DOM操作,而将注意力集中在业务逻辑上。

      另外一个疑问,ng是MVC框架吗?还是MVVM框架?官网有提到ng的设计采用了MVC的基本思想,而又不完全是MVC,因为在书写代码时我们确实是在用ng-controller这个指令(起码从名字上看,是MVC吧),但这个controller处理的业务基本上都是与view进行交互,这么看来又很接近MVVM。让我们把目光移到官网那个非醒目的title上:“AngularJS — Superheroic JavaScript MVW Framework”。


    2.2 AngularJS简单介绍

    AngularJS 重新定义了前端应用的开发方式。面对HTML和JavaScript之间的界线,它

    非但不畏缩不前,反而正面出击,提出了有效的解决方案。

    很多前端应用的开发框架,比如Backbone、EmberJS等,都要求开发者继承此框架特有的一些JavaScript对象。这种方式有其长处,但它不必要地污染了开发者自己代码的对象空间,还要求开发者去了解内存里那些抽象对象。尽管如此我们还是接受了这种方式,因为网络最初的设计无法提供 我们今天所需的交互性,于是我们需要框架,来帮我们填补JavaScript和HTML之间的鸿沟。而且有了它,你不用再“直接”操控DOM,只要给你的DOM注上metadata(即AngularJS里的directive们),然后让AngularJS来帮你操纵DOM。同时,AngularJS不依赖(也不妨碍)任何其他的框架。你甚至可以基于其它的框架来开发AngularJS应用。

    API地址:http://docs.angularjs.org/api/;

    AngularJS在github上的中文粗译版地址:https://github.com/basestyle/angularjs-cn。


    2.3 什么时候该用AngularJS

    AngularJS是一个 MV* 框架,最适于开发客户端的单页面应用。它不是个功能库,而是用来开发动态网页的框架。它专注于扩展HTML的功能,提供动态数据绑定(data binding),而且它能跟其它框架(如jQuery)合作融洽。

    如果你要开发的是单页应用,AngularJS就是你的上上之选。Gmail、Google Docs、Twitter和Facebook这样的应用,都很能发挥AngularJS的长处。但是像游戏开发之类对DOM进行大量操纵、又或者单纯需要 极高运行速度的应用,就不是AngularJS的用武之地了。


    3 AugularJS特性

    AngularJS是一个新出现的强大客户端技术,提供给大家的一种开发强大应用的方式。这种方式利用并且扩展HTML,CSS和javascript,并且弥补了它们的一些非常明显的不足。本应该使用HTML来实现而现在由它开发的动态一些内容。

    AngularJS有五个最重要的功能和特性:


    3.1 特性一:双向的数据绑定

    数据绑定可能是AngularJS最酷最实用的特性。它能够帮助你避免书写大量的初始代码从而节约开发时间。一个典型的web应用可能包含了80%的代码用来处理,查询和监听DOM。数据绑定是的代码更少,你可以专注于你的应用。

    我们想象一下Model是你的应用中的简单事实。你的Model是你用来读取或者更新的部分。数据绑定指令提供了你的Model投射到view的方法。这些投射可以无缝的,毫不影响的应用到web应用中。

    传统来说,当model变化了。 开发人员需要手动处理DOM元素并且将属性反映到这些变化中。这个一个双向的过程。一方面,model变化驱动了DOM中元素变化,另一方面,DOM元素的变化也会影响到Model。这个在用户互动中更加复杂,因为开发人员需要处理和解析

    这些互动,然后融合到一个model中,并且更新View。这是一个手动的复杂过程,当一个应用非常庞大的时候,将会是一件非常费劲的事情。

    这里肯定有更好的解决方案!那就是AngularJS的双向数据绑定,能够同步DOM和Model等等。

    这里有一个非常简单的例子,用来演示一个input输入框和<h1>元素的双向绑定(例01):


    说明:实际效果请大家看AngularJS/demo/index.html


    3.2 特性二:模板

    在AngularJS中,一个模板就是一个HTML文件。但是HTML的内容扩展了,包含了很多帮助你映射model到view的内容。

    HTML模板将会被浏览器解析到DOM中。DOM然后成为AngularJS编译器的输入。AngularJS将会遍历DOM模板来生成一些指导,即,directive(指令)。所有的指令都负责针对view来设置数据绑定。

    我们要理解AuguarJS并不把模板当做String来操作。输入AngularJS的是DOM而非string。数据绑定是DOM变化,不是字符串的连接或者innerHTML变化。使用DOM作为输入,而不是字符串,是AngularJS区别于其它的框架的最大原因。使用DOM允许你扩展指令词汇并且可以创建你自己的指令,甚至开发可重用的组件。

    最大的好处是为设计师和开发者创建了一个紧密的工作流。设计师可以像往常一样开发标签,然后开发者拿过来添加上功能,通过数据绑定将会使得这个过程非常简单。

    这里有一个例子,我们使用ng-repeat指令来循环图片数组并且加入img模板,如下:

    function AlbumCtrl($scope) {

        scope.images = [

            {"image":"img/image_01.png", "description":"Image 01 description"},

            {"image":"img/image_02.png", "description":"Image 02 description"},

            {"image":"img/image_03.png", "description":"Image 03 description"},

            {"image":"img/image_04.png", "description":"Image 04 description"},

            {"image":"img/image_05.png", "description":"Image 05 description"}

        ];

    }

    <div ng-controller="AlbumCtrl">

      <ul>

        <li ng-repeat="image in images">

          <img ng-src="http://m.cnblogs.com/142260/{{image.thumbnail}}" rel="nofollow"/>

        </li>

      </ul>

    </div>

    这里还有一件事值得提一句,AngularJS并不强制你学习一个新的语法或者从你的应用中提出你的模板。


    3.3 特性三:MVC

    针对客户端应用开发AngularJS吸收了传统的MVC基本原则。MVC或者Model-View-Controll设计模式针对不同的人可能意味不同的东西。AngularJS并不执行传统意义上的MVC,更接近于MVVM(Moodel-View-ViewModel)。

    Model

    model是应用中的简单数据。一般是简单的javascript对象。这里没有必要继承框架的classes,使用proxy对象封装或者使用特别的setter/getter方法来访问。事实上我们处理vanilla javascript的方法就是一个非常好的特性,这种方法使得我们更少使用应用的原型。

    ViewModel

    viewmodel是一个用来提供特别数据和方法从而维护指定view的对象。

    viewmodel是$scope的对象,只存在于AnguarJS的应用中。$scope只是一个简单的js对象,这个对象使用简单的API来侦测和广播状态变化。

    Controller

    controller负责设置初始状态和参数化$scope方法用以控制行为。需要指出的controller并不保存状态也不和远程服务互动。

    View

    view是AngularJS解析后渲染和绑定后生成的HTML 。这个部分帮助你创建web应用的架构。$scope拥有一个针对数据的参考,controller定义行为,view处理布局和互动。


    3.4 特性四:服务和依赖注入

    AngularJS服务其作用就是对外提供某个特定的功能。

    AngularJS拥有内建的依赖注入(DI)子系统,可以帮助开发人员更容易的开发,理解和测试应用。

    DI允许你请求你的依赖,而不是自己找寻它们。比如,我们需要一个东西,DI负责找创建并且提供给我们。

    为了而得到核心的AngularJS服务,只需要添加一个简单服务作为参数,AngularJS会侦测并且提供给你:

    function EditCtrl($scope, $location, $routeParams) {

         // Something clever here...

    }

    你也可以定义自己的服务并且让它们注入:

    angular.module('MyServiceModule', []).

        factory('notify', ['$window', function (win) {

        return function (msg) {

            win.alert(msg);

        };

    }]);

    function myController(scope, notifyService) {

        scope.callNotify = function (msg) {

            notifyService(msg);

        };

    }

    myController.$inject = ['$scope', 'notify'];


    3.5 特性五:指令(Directives)

    指令是我个人最喜欢的特性。你是不是也希望浏览器可以做点儿有意思的事情?那么AngularJS可以做到。

    指令可以用来创建自定义的标签。它们可以用来装饰元素或者操作DOM属性。可以作为标签、属性、注释和类名使用。

    这里是一个例子,它监听一个事件并且针对的更新它的$scope ,如下:

    myModule.directive('myComponent', function(mySharedService) {

        return {

            restrict: 'E',

            controller: function($scope, $attrs, mySharedService) {

                $scope.$on('handleBroadcast', function() {

                    $scope.message = 'Directive: ' mySharedService.message;

                });

            },

            replace: true,

            template: '<input>'

        };

    });

    然后,你可以使用这个自定义的directive来使用:

    <my-component ng-model="message"></my-component>

    使用一系列的组件来创建你自己的应用将会让你更方便的添加,删除和更新功能。

     


    4 功能介绍


    4.1数据绑定

    AngularJS的双向数据绑定,意味着你可以在Mode(JS)中改变数据,而这些变动立刻就会自动出现在View上,反之亦然。即:一方面可以做到model变化驱动了DOM中元素变化,另一方面也可以做到DOM元素的变化也会影响到Model。

    在我们使用jQuery的时候,代码中会大量充斥类似这样的语句:var val = $(‘#id’).val(); $(‘#id’).html(str);等等,即频繁的DOM操作(读取和写入),其实我们的最终目的并不是要操作DOM,而是要实现业务逻辑。ng的绑定将让你摆脱DOM操作,只要模板与数据通过声明进行了绑定,两者将随时保持同步,最新的数据会实时显示在页面中,页面中用户修改的数据也会实时被记录在数据模型中。

    从View到Controller再到View的数据交互(例01):

    <html ng-app="demoApp">

    ……

    <input type="text" ng-model="user.name" placeholder="请输入名称"/>

    Hello, {{ user.name }}!

    ……

    关键: ng-app 、 ng-model 和 { {user.name } }

    首先: <html>元素的ng-app属性。标识这个DOM里面的内容将启用AngularJS应用。

    其次:告诉AngularJS,对页面上的“user.name” 这个Model进行双向数据绑定。

    第三:告诉AngularJS,在“{{ user.name}}”这个指令模版上显示“user.name”这个Model的数据。

    从Server到Controller再到View的数据交互(例02):

    <html ng-app="demoApp">

    ……

    <div  ng-controller="demoController">

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

    <a href="javascript:void(0);" target="_blank" rel="nofollow">获取名字</a>

    ……

    demoApp.controller("demoController", function($http, $scope){

    $scope. getAjaxUser = function(){

    // $http.get({url:"../xxx.action"}).success(function(data){

    // $scope.user= data;

    // });

    $scope.user = {"name":"从JOSN中获取的名称","age":22};

    };

    });

    改变$scope中的user,View也会自动更新。


    4.2 scopes、module、controller


    4.2.1 scopes

    $scope是一个把view(一个DOM元素)连结到controller上的对象。在我们的MVC结构里,这个 $scope 将成为model,它提供一个绑定到DOM元素(以及其子元素)上的excecution context。

    尽管听起来有点复杂,但 $scope 实际上就是一个JavaScript对象,controller和view都可以访问它,所以我们可以利用它在两者间传递信息。在这个 $scope 对象里,我们既存储数据,又存储将要运行在view上的函数。

    每一个Angular应用都会有一个 $rootScope。这个 $rootScope 是最顶级的scope,它对应着含有 ng-app 指令属性的那个DOM元素。

    app.run(function($rootScope) { $rootScope.name = "张三"; });

    如果页面上没有明确设定 $scope ,Angular 就会把数据和函数都绑定到这里, 第一部分中的例子就是靠这一点成功运行的。

    这样,我们就可以在view的任何地方访问这个name属性,使用模版表达式{{}},像这样:

    {{ name }}  


    4.2.2 module

    首先需要明确一下模板的概念。在我还不知道有模板这个东西的时候,曾经用js拼接出很长的HTML字符串,然后append到页面中,这种方式想想真是又土又笨。后来又看到可以把HTML代码包裹在一个<script>标签中当作模板,然后按需要取来使用。

    在ng中,模板十分简单,它就是我们页面上的HTML代码,不需要附加任何额外的东西。在模板中可以使用各种指令来增强它的功能,这些指令可以让你把模板和数据巧妙的绑定起来。

    在<html>标签上多了一个属性ng-app=”MyApp”,它的作用就是用来指定ng的作用域是在<html>标签以内部分。在js中,我们调用angular对象的module方法来声明一个模块,模块的名字和ng-app的值对应。这样声明一下就可以让ng运行起来了。

    示例:

    <html ng-app="demoApp">

    var demoApp = angular.module('demoApp', []);


    4.2.3 ng-controller

    要明确创建一个$scope 对象,我们就要给DOM元素安上一个controller对象,使用的是ng-controller 指令属性:

    <div ng-controller="MyController"> {{ person.name }} </div>  

    ng-controller指令给所在的DOM元素创建了一个新的$scope 对象,并将这个$scope 对象包含进外层DOM元素的$scope 对象里。在上面的例子里,这个外层DOM元素的$scope 对象,就是$rootScope 对象。这个scope链是这样的:

     

     

    所有scope都遵循原型继承(prototypal inheritance),这意味着它们都能访问父scope们。对任何属性和方法,如果AngularJS在当前scope上找不到,就会到父 scope上去找,如果在父scope上也没找到,就会继续向上回溯,一直到$rootScope 上。即如果controller是多层嵌套的,就会从最里面一直往外找,这个scope链是这样的:

     

    唯一的例外:有些指令属性可以选择性地创建一个独立的scope,让这个scope不继承它的父scope们,这个会在指令详解中说明。


    4.3 ajax

    $http 服务是AngularJS的核心服务之一,它帮助我们通过XMLHttpRequest对象或JSONP与远程HTTP服务进行交流。

    $http 服务是这样一个函数:它接受一个设置对象,其中指定了如何创建HTTP请求;它将返回一个承诺(*参考JavaScript异步编程的promise模式),其中提供两个方法: success方法和error方法。

    demoApp.controller("demoController", function($http, $scope){

    $scope. getAjaxUser = function(){

    $http.get({url:"../xxx.action"}).success(function(data){

    alert(data);

    }).error(function(){

    Alert(“出错了!”);

    });

     

    };

    });

    AngularJS的AJAX与jquery等框架的AJAX基本一致,这里就不多说了。


    4.4表达式

    ng中的表达式与javascript表达式类似但是不可以划等号,它是ng自己定义的一套模式。表达式可以作为指令的值,如ng-modle=”people.name”、ng-click=”showMe()”,看起来是如此像字符串,故而也叫字符串表达式。也可以在标记中使用表达式,如{{1 2}},或者与过滤器一起使用{{1 2 | currency}}。在框架内部,字符串不会简单的使用eval()来执行,而是有一个专门的$parse服务来处理。在ng表达式中不可以使用循环语句、判断语句,事实上在模板中使用复杂的表达式也是一个不推荐的做法,这样视图与逻辑就混杂在一起了

    我们在使用其他模板库时,一般都会有模板的循环输出、分支输出、逻辑判断等类似的控制。

    要想理解指令属性的运作,我们必须先理解表达式。在之前的例子里我们已经见过表达式,例如 {{ user.name }}。

    请查看例03、例04、例05。

    {{ 8 1 }} 9

    {{ person }} {"name":"Ari Lerner"}

    {{ 10 * 3.3 | currency }} $33.00

    表达式粗略来看有点像 eval(javascript) 的结果。它们会经过Angular.js的处理,从而拥有以下重要而独特的性质:

    l 所有表达式都在scope这个context里被执行,因此可以使用所有本地 $scope 中的变量。

    l 如果一个表达式的执行导致类型错误或引用错误,这些错误将不会被抛出。

    l 表达式里不允许任何控制函数流程的功能(如if/else等条件语句)

    l 表达式可接受一个或多个串联起来的过滤器。


    4.5过滤器

    过滤器(filter)正如其名,作用就是接收一个输入,通过某个规则进行处理,然后返回处理后的结果。主要用在数据的格式化上,例如获取一个数组中的子集,对数组中的元素进行排序等。过滤器通常是伴随标记来使用的,将你model中的数据格式化为需要的格式。表单的控制功能主要涉及到数据验证以及表单控件的增强。ng内置了一些过滤器,它们是:

    currency(货币)、date(日期)、filter(子串匹配)、json(格式化json对象)、limitTo(限制个数)、lowercase(小写)、uppercase(大写)、number(数字)、orderBy(排序)。


    4.5.1过滤器使用方式

    总共九种。除此之外还可以自定义过滤器,这个就强大了,可以满足任何要求的数据处理。Filter还是很简单的,需要明白的是内置的filter如何使用,以及自己如何定义一个filter。

    filter的两种使用方法:

      1. 在模板中使用filter

      我们可以直接在{{}}中使用filter,跟在表达式后面用 | 分割,语法如下:

    {{ expression | filter }}

    也可以多个filter连用,上一个filter的输出将作为下一个filter的输入:

    {{ expression | filter1 | filter2 | ... }}  

    filter可以接收参数,参数用 : 进行分割,如下:

    {{ expression | filter:argument1:argument2:... }}  

    除了对{{}}中的数据进行格式化,我们还可以在指令中使用filter,例如先对数组array进行过滤处理,然后再循环输出:

    <span ng-repeat="a in array | filter ">  

    2. 在controller和service中使用filter

      我们的js代码中也可以使用过滤器,方式就是我们熟悉的依赖注入,例如我要在controller中使用currency过滤器,只需将它注入到该controller中即可,代码如下:

    app.controller('testC',function($scope,currencyFilter){

        $scope.num = currencyFilter(123534);  

    }  

    在模板中使用{{num}}就可以直接输出$123,534.00了!在服务中使用filter也是同样的道理。

      如果你要在controller中使用多个filter,并不需要一个一个注入吗,ng提供了一个$filter服务可以来调用所需的filter,你只需注入一个$filter就够了,使用方法如下:

    app.controller('testC',function($scope,$filter){

    $scope.num = $filter('currency')(123534);  

    $scope.date = $filter('date')(new Date());  

    }  

    可以达到同样的效果。好处是你可以方便使用不同的filter了。


    4.5.2 ng的内置过滤器

    ng内置了九种过滤器,使用方法都非常简单,看文档即懂。不过为了以后不去翻它的文档,我在这里还是做一个详细的记录。

    currency(货币)、date(日期)、filter(子串匹配)、json(格式化json对象)、limitTo(限制个数)、lowercase(小写)、uppercase(大写)、number(数字)、orderBy(排序)
    1. currency (货币处理)

      使用currency可以将数字格式化为货币,默认是美元符号,你可以自己传入所需的符号,例如我传入人民币:

    {{num | currency : '¥'}}  
    2. date (日期格式化)

      原生的js对日期的格式化能力有限,ng提供的date过滤器基本可以满足一般的格式化要求。用法如下:

    {{date | date : 'yyyy-MM-dd hh:mm:ss EEEE'}}  

    参数用来指定所要的格式,y M d h m s E 分别表示 年 月 日 时 分 秒 星期,你可以自由组合它们。也可以使用不同的个数来限制格式化的位数。另外参数也可以使用特定的描述性字符串,例如“shortTime”将会把时间格式为12:05 pm这样的。ng提供了八种描述性的字符串,个人觉得这些有点多余,我完全可以根据自己的意愿组合出想要的格式,不愿意去记这么多单词~
    3. filter(匹配子串)

      这个名叫filter的filter。用来处理一个数组,然后可以过滤出含有某个子串的元素,作为一个子数组来返回。可以是字符串数组,也可以是对象数组。如果是对象数组,可以匹配属性的值。它接收一个参数,用来定义子串的匹配规则。下面举个例子说明一下参数的用法,我用现在特别火的几个孩子定义了一个数组:

    $scope.childrenArray = [

            {name:'kimi',age:3},

            {name:'cindy',age:4},

            {name:'anglar',age:4},

            {name:'shitou',age:6},

            {name:'tiantian',age:5}

    ];

    $scope.func = function(e){return e.age>4;}{{ childrenArray | filter : 'a' }} //匹配属性值中含有a的

    {{ childrenArray | filter : 4 }}  //匹配属性值中含有4的

    {{ childrenArray | filter : {name : 'i'} }} //参数是对象,匹配name属性中含有i的

    {{childrenArray | filter : func }}  //参数是函数,指定返回age>4的  
    4. json(格式化json对象)

      json过滤器可以把一个js对象格式化为json字符串,没有参数。这东西有什么用呢,我一般也不会在页面上输出一个json串啊,官网说它可以用来进行调试,嗯,是个不错的选择。或者,也可以用在js中使用,作用就和我们熟悉的JSON.stringify()一样。用法超级简单:

    {{ jsonTest | json}}
    5. limitTo(限制数组长度或字符串长度)

      limitTo过滤器用来截取数组或字符串,接收一个参数用来指定截取的长度,如果参数是负值,则从数组尾部开始截取。个人觉得这个filter有点鸡肋,首先只能从数组或字符串的开头/尾部进行截取,其次,js原生的函数就可以代替它了,看看怎么用吧:

    {{ childrenArray | limitTo : 2 }}  //将会显示数组中的前两项  
    6. lowercase(小写)

      把数据转化为全部小写。太简单了,不多解释。同样是很鸡肋的一个filter,没有参数,只能把整个字符串变为小写,不能指定字母。怎么用我都懒得写了。
    7. uppercase(大写)

      同上。
    8. number(格式化数字)

      number过滤器可以为一个数字加上千位分割,像这样,123,456,789。同时接收一个参数,可以指定float类型保留几位小数:

    {{ num | number : 2 }}  
    9. orderBy(排序)

      orderBy过滤器可以将一个数组中的元素进行排序,接收一个参数来指定排序规则,参数可以是一个字符串,表示以该属性名称进行排序。可以是一个函数,定义排序属性。还可以是一个数组,表示依次按数组中的属性值进行排序(若按第一项比较的值相等,再按第二项比较),还是拿上面的孩子数组举例:

    <div>{{ childrenArray | orderBy : 'age' }}</div>      //按age属性值进行排序,若是-age,则倒序

    <div>{{ childrenArray | orderBy : orderFunc }}</div>   //按照函数的返回值进行排序

    <div>{{ childrenArray | orderBy : ['age','name'] }}</div>  //如果age相同,按照name进行排序  内置的过滤器介绍完了,写的我都快睡着了。。。正如你所看到的,ng内置的过滤器也并不是万能的,事实上好多都比较鸡肋。更个性化的需求就需要我们来定义自己的过滤器了,下面来看看如何自定义过滤器。
    4.5.3自定义过滤器及示例

      filter的自定义方式也很简单,使用module的filter方法,返回一个函数,该函数接收

    输入值,并返回处理后的结果。话不多说,我们来写一个看看。比如我需要一个过滤器,它可以返回一个数组中下标为奇数的元素,代码如下:

    app.filter('odditems',function(){

        return function(inputArray){

            var array = [];

            for(var i=0;i<inputArray.length;i ){

                if(i%2!==0){

                    array.push(inputArray[i]);

                }

            }

            return array;

        }

    });  

    格式就是这样,你的处理逻辑就写在内部的那个闭包函数中。你也可以让自己的过滤器接收参数,参数就定义在return的那个函数中,作为第二个参数,或者更多个参数也可以。

    自定义过滤器实例(例04):

    /* View html */

    First name:<input ng-model="user.firstName"/><br/>

    Last  name:<input ng-model="user.lastName"/> <br/>

    First name:{{user.firstName}}      Last  name:{{user.lastName}} <br/>

    Fullname:{{user | flFullname}}<br/>

    Fullname:{{user | flFullname:"-"}}<br/>

    Fullname:{{user | flFullname:"•" | uppercase }}

    /* Controller js */

    demoApp.filter("flFullname", function() {

        return function(user, sep) {

            sep = sep || " ";

            user = user || {};

            fullName = "";

            if(user.firstName){fullName = user.firstName;}

            if(user.lastName){fullName = fullName sep user.lastName;}

            if(fullName && fullName.length>0){return fullName;

            }else{return "";}

        };

    });


    4.6指令(directive)

      通过使用模板,我们可以把model和controller中的数据组装起来呈现给浏览器,还可以通过数据绑定,实时更新视图,让我们的页面变成动态的。

      模板中可以使用的东西包括以下四种:

    1.指令(directive):ng提供的或者自定义的标签和属性,用来增强HTML表现力;

    2.标记(markup):即双大括号{{}},可将数据单向绑定到HTML中;

    3.过滤器(filter):用来格式化输出数据;

    4.表单控制:用来增强表单的验证功能。

    其中,指令无疑是使用量最大的,ng内置了很多指令用来控制模板,如ng-repeat,ng-class,也有很多指令来帮你完成业务逻辑,如ng-controller,ng-model。

    指令的几种使用方式如下:

    l 作为标签:<my-dir></my-dir>

    l 作为属性:<span my-dir="exp"></span>

    l 作为注释:<!-- directive: my-dir exp -->

    l 作为类名:<span class="my-dir: exp;"></span>

    其实常用的就是作为标签和属性。
    4.6.1样式相关的指令

      既然模板就是普通的HTML,那我首要关心的就是样式的控制,元素的定位、字体、背景色等等如何可以灵活控制。下面来看看常用的样式控制指令。

    1. ng-class

       ng-class用来给元素绑定类名,其表达式的返回值可以是以下三种:

    l 类名字符串,可以用空格分割多个类名,如’redtext boldtext’;

    l 类名数组,数组中的每一项都会层叠起来生效;

    l 一个名值对应的map,其键值为类名,值为boolean类型,当值为true时,该类会被加在元素上。

      下面来看一个使用map的例子:

    ng-class测试

    红色 加粗 删除线

    map:{redtext:{{red}}, boldtext:{{bold}}, striketext:{{strike}}}

      如果你想拼接一个类名出来,可以使用插值表达式,如:

      <div class=”{{style}}text”>字体样式测试</div>

      然后在controller中指定style的值:

      $scope.style = ‘red’;

      注意我用了class而不是ng-class,这是不可以对换的,官方的文档也未做说明,姑且认为这是ng的语法规则吧。

      与ng-class相近的,ng还提供了ng-class-odd、ng-class-even两个指令,用来配合ng-repeat分别在奇数列和偶数列使用对应的类。这个用来在表格中实现隔行换色再方便不过了。

    2. ng-style

      ng-style用来绑定元素的css样式,其表达式的返回值为一个js对象,键为css样式名,值为该样式对应的合法取值。用法比较简单:

    <div ng-style="{color:'red'}">ng-style测试</div>

    <div ng-style="style">ng-style测试</div>

    $scope.style = {color:'red'};  

    3. ng-show,ng-hide

       对于比较常用的元素显隐控制,ng也做了封装,ng-show和ng-hide的值为boolean类型的表达式,当值为true时,对应的show或hide生效。框架会用display:block和display:none来控制元素的显隐。


    4.6.2表单控件功能相关指令

      对于常用的表单控件功能,ng也做了封装,方便灵活控制。

      ng-checked控制radio和checkbox的选中状态

      ng-selected控制下拉框的选中状态

      ng-disabled控制失效状态

      ng-multiple控制多选

      ng-readonly控制只读状态

      以上指令的取值均为boolean类型,当值为true时相关状态生效,道理比较简单就不多做解释。注意: 上面的这些只是单向绑定,即只是从数据到模板,不能反作用于数据。要双向绑定,还是要使用 ng-model 。


    4.6.3事件绑定相关指令

    事件绑定是javascrpt中比较重要的一部分内容,ng对此也做了详细的封装,正如我们之前使用过的ng-click一样,事件的指令如下:

    ng-click

      ng-change

      ng-dblclick

      ng-mousedown

      ng-mouseenter

      ng-mouseleave

      ng-mousemove

      ng-mouseover

      ng-mouseup

      ng-submit

      事件绑定指令的取值为函数,并且需要加上括号,例如:

    <select ng-change=”change($event)”></select>  

    然后在controller中定义如下:

    $scope.change = function($event){

             alert($event.target);

             //……………………

    }  

    在模板中可以用变量$event将事件对象传递到controller中。

    对于ng的这种设计,一些人有所质疑,视图与事件绑定混在一起到底好不好?我们不是要讲究视图与逻辑分离吗?如此一来,把事件的绑定又变回了内联的,岂不是历史的倒退。我也一样对此表示不解,因为不写onclick已经很多年。。。但既然已经存在了,我们不妨往合理的方向上想一想,或许ng的设计者压根就不想让模板成为单纯的视图层,本来就是想增强HTML,让它有一点业务能力。这么想的话似乎也能想通,好吧,先欺骗一下自己吧~


    4.6.4特殊的ng-src和ng-href

    在说明这两个指令的特殊之前,需要先了解一下ng的启动及执行过程,如下图:

     

    1) 浏览器加载静态HTML文件并解析为DOM;

      2) 浏览器加载angular.js文件;

      3) angular监听DOMContentLoaded 事件,监听到时开始启动;

      4) angular寻找ng-app指令,确定作用范围;

      5) 找到app中定义的Module使用$injector服务进行依赖注入;

      6) 根据$injector服务创建$compile服务用于编译;

      7) $compile服务编译DOM中的指令、过滤器等;

      8) 使用ng-init指令,将作用域中的变量进行替换;

      9) 最后生成了我们在最终视图。

      可以看到,ng框架是在DOMcontent加载完毕后才开始发挥作用。假如我们模板中有一张图片如下:

      <img src="http://m.cnblogs.com/142260/”{{imgUrl}}” />

      那么在页面开始加载到ng编译完成之前,页面上会一直显示一张错误的图片,因为路径{{imgUrl}}还未被替换。

      为了避免这种情况,我们使用ng-src指令,这样在路径被正确得到之前就不会显示找不到图片。同理,<a>标签的href属性也需要换成ng-href,这样页面上就不会先出现一个地址错误的链接。

    顺着这个思路再多想一点,我们在模板中使用{{}}显示数据时,在ng编译完成之前页面上岂不是会显示出大括号及里面的表达式?确实是这样。为了避免这个,ng中有一个与{{}}等同的指令:ng-bind,同样用于单向绑定,在页面刚加载的时候就不会显示出对用户无用的数据了。尽管这样你可能不但没舒心反而更纠结了,{{}}那么好用易理解,还不能用了不成?好消息是我们依然可以使用。因为我编写的是单页面应用,页面只会在加载index.html的时

    候出这个问题,只需在index.html中的模板中换成ng-bind就行。其他的模板是我们动态加载的,就可以放心使用{{}}了。


    4.6.5 自定义指令示例

    下面我们来解析下指令的例子(例07)。

    1.首先,我们定义一个名为userInfo的指令:

    demoApp.directive('userInfo',function(){

    return {

            restrict : 'E',

            templateUrl : 'userInfoTemplate.html',

            replace : true,

            transclude : true,

            scope : {

                mytitle : '=etitle'

            },

            link : function(scope,element,attrs){

                scope.showText = false;

                scope.toggleText = function(){

                    scope.showText = ! scope.showText;

                }

            }

        };

    })  

    Restrict为'E':用作标签;replace为true:用模板替换当前标签;transclude为true:将当前元素的内容转移到模板中;scope 为 {mytitle : '=etitle'}:定义一个名为mytitle的MODEL,其值指向当前元素的etitle属性;templateUrl为'userInfoTemplate.html':模板内容为ng-template定义ID为userInfoTemplate.html的内容;link:指定所包含的行为。其具体的说明及其他参数,请参考:6.2指令详解。

    2. userInfoTemplate.html模板为:

    <script type="text/ng-template" id="userInfoTemplate.html">

    <div class="mybox">

    <div class="mytitle" style="cursor: pointer;" ng-click="toggleText()">

    { {mytitle} }

    </div>

    <div ng-transclude ng-show="showText">

    </div>

    </div>

    </script>

    将当前元素的内容添加到有ng-transclude属性的这个DIV下,默认是隐藏的。

    3.Controller信息:

    demoApp.controller("test7Controller", function($scope){

    $scope.title = '个人简介';

    $scope.text = '大家好,我正在研究AngularJs,欢迎大家与我交流。';

    $scope.updateInfo = function (){

    $scope.title = '个人信息';

    $scope.text = '大家好,今天天气真好!';

    }

    });

    4.指令使用方式(View信息)为:

    <user-info etitle="title">{ {text} }</user-info>

    Etitle指向Controller中的$scope.title。注意命名方式:指令名为userInfo,对应的标签为user-info。


    4.7服务(service)
    4.7.1服务介绍

      服务这个概念其实并不陌生,在其他语言中如java便有这样的概念,其作用就是对外提供某个特定的功能,如消息服务,文件压缩服务等,是一个独立的模块。ng的服务是这样定义的:

    Angular services are singletons objects or functions that carry out specific tasks common to web apps.

    它是一个单例对象或函数,对外提供特定的功能。

    首先是一个单例,即无论这个服务被注入到任何地方,对象始终只有一个实例。

    其次这与我们自己定义一个function然后在其他地方调用不同,因为服务被定义在一个模块中,所以其使用范围是可以被我们管理的。ng的避免全局变量污染意识非常强。

      ng提供了很多内置的服务,可以到API中查看http://docs.angularjs.org/api/。知道了概念,我们来拉一个service出来溜溜,看看到底是个什么用法。  

      我们在controller中直接声明$location服务,这依靠ng的依赖注入机制。$location提供地址栏相关的服务,我们在此只是简单的获取当前的地址。

      服务的使用是如此简单,我们可以把服务注入到controller、指令或者是其他服务中。
    4.7.2自定义服务

      如同指令一样,系统内置的服务以$开头,我们也可以自己定义一个服务。定义服务的方式有如下几种:

    l 使用系统内置的$provide服务;

    l 使用Module的factory方法;

    l 使用Module的service方法。

      下面通过一个小例子来分别试验一下。我们定义一个名为remoteData服务,它可以从远程获取数据,这也是我们在程序中经常使用的功能。不过我这里没有远程服务器,就写死一点数据模拟一下。

    //使用$provide来定义

    var app = angular.module('MyApp', [], function($provide) {

        $provide.factory('remoteData', function() {

     var data = {name:'n',value:'v'};

            return data;

        });

    });

    //使用factory方法

    app.factory('remoteData',function(){

        var data = {name:'n',value:'v'};

        return data;

    });

    //使用service方法

    app.service('remoteData',function(){

        this.name = 'n';

        this.value = 'v';

    });

    Module的factory和$provide的factory方法是一模一样的,从官网文档看它们其实就是一回事。至于Module内部是如何调用的,我此处并不打算深究,我只要知道怎么用就好了。

    再看Module的service方法,它没有return任何东西,是因为service方法本身返回一个构造器,系统会自动使用new关键字来创建出一个对象。所以我们看到在构造器函数内可以使用this,这样调用该服务的地方便可以直接通过remoteData.name来访问数据了。
    4.7.3管理服务的依赖关系

      服务与服务中间可以有依赖关系,例如我们这里定义一个名为validate的服务,它的作用是验证数据是否合法,它需要依赖我们从远程获取数据的服务remoteData。代码如下:

       在factory的参数中,我们可以直接传入服务remoteData,ng的依赖注入机制便帮我们做好了其他工作。不过一定要保证这个参数的名称与服务名称一致,ng是根据名称来识别的。若参数的名次与服务名称不一致,你就必须显示的声明一下,方式如下:

    app.factory('validate',['remoteData',function(remoteDataService){

        return function(){

            if(remoteDataService.name=='n'){

                alert('验证通过');

            }

        };

    }]);  

    我们在controller中注入服务也是同样的道理,使用的名称需要与服务名称一致才可以正确注入。否则,你必须使用$inject来手动指定注入的服务。比如:

    function testC(scope,rd){

        scope.getData = function(){

            alert('name:' rd.name '   value:' rd.value);

        }

    }

    testC.$inject = ['$scope','remoteData'];

     

      在controller中注入服务,也可以在定义controller时使用数组作为第二个参数,在此处

    把服务注入进去,这样在函数体中使用不一致的服务名称也是可以的,不过要确保注入的顺序是一致的,如:

    app.controller('testC',['$scope','remoteData',function($scope,rd){

        $scope.getData = function(){

            alert('name:' rd.name '   value:' rd.value);

        }

    }]);
    4.7.4 自定义服务示例

    接下来让我们看下例子(例08 自定义服务)代码,自定义userService服务:

    demoApp.factory('userService', ['$http', function($http) {

    var doGetUser = function(userId, path) {

    //return $http({

    //method: 'JSONP',

    //url: path

    //});

    /*手动指定数据*/

    var data = {userId:"woshishui",userName:"我是谁",userInfo:"我是谁!我是谁!"};;

    if(userId=='zhangsan'){

    data = {userId:"zhangsan",userName:"张三",userInfo:"我是张三,我为自己"};

    }else if(userId=='lisi'){

    data = {userId:"lisi",userName:"李四",userInfo:"我是李四,我为卿狂!"};

    }

    return data;

    }

    return {

    /*userService对外暴露的函数,可有多个*/

    getUser: function(userId) {

    return doGetUser(userId, '../xxx/xxx.action');

    }

    };

    }]);

    我们创建了一个只有一个方法的userService,getUser为这个服务从后台获取用户信息的函数,并且对外暴露。当然,由于这是一个静态的例子,无法访问后台,那么我们便制定其返回的数据。

    然后我们把这个服务添加到我们的controller中。我们建立一个controller并加载(或者注入)userService作为运行时依赖,我们把service的名字作为参数传递给controller 函数:

    demoApp.controller("test8Controller", function($scope,userService){

    /*文章信息*/

    $scope.articles = [{

    title : "爱飞像风",

    userId : "zhangsan",

    userName : "张三"

    },{

    title : "无法停止的雨",

    userId : "lisi",

    userName : "李四"

    }];

    $scope.showUserInfo = false;//显示作者详细信息开关

    $scope.currentUser = {}; //当前选中的作者

    $scope.getUserInfo = function(userId){

    $scope.currentUser = userService.getUser(userId);

    //调用 userService的getUser函数

    $scope.showUserInfo = true;

    setTimeout(function(){//定时器:隐藏作者详细信息

    $scope.showUserInfo = false;

    },3000);

    }

    });

    我们的userService注入到我们的test8Controller后,我们就可以像使用其他服务(我们前面提到的$http服务)一样的使用userService了。

    相关的HTML代码如下:

    /* View HTML*/

    <tr ng-repeat="article_ in articles">

    <td>

    {{article_.title}}

    </td>

    <td>

    <a href="javascript:void(0);" target="_blank" rel="nofollow">

    </td>

    </tr>

    ......

    <div ng-show="showUserInfo">

    用户ID:{{currentUser.userId}}<br/>

    用户名:{{currentUser.userName}}<br/>

    用户简介:{{currentUser.userInfo}}<br/>

    </div>


    4.8依赖注入DI

    通过依赖注入,ng想要推崇一种声明式的开发方式,即当我们需要使用某一模块或服务时,不需要关心此模块内部如何实现,只需声明一下就可以使用了。在多处使用只需进行多次声明,大大提高可复用性。

      比如我们的controller,在定义的时候用到一个$scope参数。

    app.controller('testC',function($scope){});  

    如果我们在此处还需操作其他的东西,比如与浏览器地址栏进行交互。我们只需再多添

    一个参数$location进去:

    app.controller('testC',function($scope,$location){});  

    这样便可以通过$location来与地址栏进行交互了,我们仅仅是声明了一下,所需的其他代码,框架已经帮我们注入了。我们很明显的感觉到了这个函数已经不是常规意义上的javascript函数了,在常规的函数中,把形参换一个名字照样可以运行,但在此处若是把$scope换成别的名字,程序便不能运行了。因为这是已经定义好的服务名称。

    这便是依赖注入机制。顺理成章的推断,我们可以自己定义模块和服务,然后在需要的地方进行声明,由框架来替我们注入。

    来看下我们如何定义一个服务:

    app.factory('tpls',function(){

        return ['tpl1','tpl2','tpl3','tpl4'];

    });  

    看上去相当简单,是因为我在这里仅仅是直接返回一个数组。在实际应用中,这里应该是需要向服务器发起一个请求,来获取到这些模板们。服务的定义方式有好几种,包括使用provider方法、使用factory方法,使用service方法。它们之间的区别暂且不关心。我们现在只要能创建一个服务出来就可以了。我使用了factory方法。一个需要注意的地方是,框架提供的服务名字都是由$开头的,所以我们自己定义的最好不要用$开头,防止发生命名冲突。

    定义好一个服务后,我们就可以在控制器中声明使用了,如下:

    app.controller('testC',function($scope,tpls){

        $scope.question = questionModel;

        $scope.nowTime = new Date().valueOf();

        $scope.templates = tpls; //赋值到$scope中

        $scope.addOption = function(){

            var o = {content:''};

            $scope.question.options.push(o);

        };

        $scope.delOption = function(index){

            $scope.question.options.splice(index,1);

        };

    });  

    此时,若在模板中书写如下代码,我们便可以获取到服务tpls所提供的数据了:

    模板:

    <a href="javascript:void(0);" target="_blank" rel="nofollow">


    4.9路由(route)

    在谈路由机制前有必要先提一下现在比较流行的单页面应用,就是所谓的single page APP。为了实现无刷新的视图切换,我们通常会用ajax请求从后台取数据,然后套上HTML模板渲染在页面上,然而ajax的一个致命缺点就是导致浏览器后退按钮失效,尽管我们可以在页面上放一个大大的返回按钮,让用户点击返回来导航,但总是无法避免用户习惯性的点后退。解决此问题的一个方法是使用hash,监听hashchange事件来进行视图切换,另一个方法是用HTML5的history API,通过pushState()记录操作历史,监听popstate事件来进行视图切换,也有人把这叫pjax技术。基本流程如下:

    如此一来,便形成了通过地址栏进行导航的深度链接(deeplinking ),也就是我们所需要的路由机制。通过路由机制,一个单页应用的各个视图就可以很好的组织起来了。


    4.9.1 ngRoute内容

      ng的路由机制是靠ngRoute提供的,通过hash和history两种方式实现了路由,可以检测浏览器是否支持history来灵活调用相应的方式。ng的路由(ngRoute)是一个单独的模块,包含以下内容:

    l 服务$routeProvider用来定义一个路由表,即地址栏与视图模板的映射

    l 服务$routeParams保存了地址栏中的参数,例如{id : 1, name : 'tom'}

    l 服务$route完成路由匹配,并且提供路由相关的属性访问及事件,如访问当前路由对应的controller

    l 指令ngView用来在主视图中指定加载子视图的区域

     以上内容再加上$location服务,我们就可以实现一个单页面应用了。下面来看一下具体如何使用这些内容。


    4.9.2 ng的路由机制

      第一步:引入文件和依赖

      ngRoute模块包含在一个单独的文件中,所以第一步需要在页面上引入这个文件,如下:

    <script src="http://code.angularjs.org/1.2.8/angular.min.js" rel="nofollow"/>

    <script src="http://code.angularjs.org/1.2.8/angular-route.min.js" rel="nofollow"/>  

    光引入还不够,我们还需在模块声明中注入对ngRoute的依赖,如下:

    var app = angular.module('MyApp', ['ngRoute']);  

    完成了这些,我们就可以在模板或是controller中使用上面的服务和指令了。下面我们需要定义一个路由表。

      第二步:定义路由表

      $routeProvider提供了定义路由表的服务,它有两个核心方法,when(path,route)和otherwise(params),先看一下核心中的核心when(path,route)方法。

      when(path,route)方法接收两个参数,path是一个string类型,表示该条路由规则所匹配的路径,它将与地址栏的内容($location.path)值进行匹配。如果需要匹配参数,可以在path中使用冒号加名称的方式,如:path为/show/:name,如果地址栏是/show/tom,那么参数name和所对应的值tom便会被保存在$routeParams中,像这样:{name : tom}。我们也可以用*进行模糊匹配,如:/show*/:name将匹配/showInfo/tom。

      route参数是一个object,用来指定当path匹配后所需的一系列配置项,包括以下内容:

    l controller //function或string类型。在当前模板上执行的controller函数,生成新的scope;

    l controllerAs //string类型,为controller指定别名;

    l template //string或function类型,视图z所用的模板,这部分内容将被ngView引用;

    l templateUrl //string或function类型,当视图模板为单独的html文件或是使用了<script type="text/ng-template">定义模板时使用;

    l resolve //指定当前controller所依赖的其他模块;

    l redirectTo //重定向的地址。

    最简单情况,我们定义一个html文件为模板,并初始化一个指定的controller:

    function emailRouteConfig($routeProvider){

        $routeProvider.when('/show', {

            controller: ShowController,

            templateUrl: 'show.html'

        }).

        when('/put/:name',{

           controller: PutController,

           templateUrl: 'put.html'

        });  

    };  

    otherwise(params)方法对应路径匹配不到时的情况,这时候我们可以配置一个redirectTo参数,让它重定向到404页面或者是首页。

      第三步:在主视图模板中指定加载子视图的位置

      我们的单页面程序都是局部刷新的,那这个“局部”是哪里呢,这就轮到ngView出马了,只需在模板中简单的使用此指令,在哪里用,哪里就是“局部”。例如:

    <div ng-view></div>  或:<ng-view></ng-view>  

    我们的子视图将会在此处被引入进来。完成这三步后,你的程序的路由就配置好了。


    4.9.3 路由示例

    下面我们将用一个例子(例09)来说明路由的使用方式及步骤:

    1.为demoApp添加一个路由,代码如下:

    demoApp.config(['$routeProvider',function($routeProvider) {  

    $routeProvider.when('/list', {  

    templateUrl: 'route/list.html',  

      controller: 'routeListController'

    }).when('/list/:id', {  

      templateUrl: 'route/detail.html',

       controller: 'routeDetailController'

      }).otherwise({  

            redirectTo: '/list'  

         });  

    }]);

    /list 对应为:route/list.html页面,显示用户列表;/list/:id对应于route/detail.html页面,显示用户详细信息。

    2.为list.html和detail.html分别声明Controller:routeListController和routeDetailController。

    demoApp.controller('routeListController',function($scope) {  

    $scope.users = [{userId:"zhangsan",userName:"张三",userInfo:"我是张三,我为自己带盐!"},

    {userId:"lisi",userName:"李四",userInfo:"我是李四,我为卿狂!"},

    {userId:"woshishui",userName:"我是谁",userInfo:"我是谁!我是谁!我是谁!"}];

     

    });  

    demoApp.controller('routeDetailController',function($scope, $routeParams, userService) {  

        $scope.userDetail = userService.getUser($routeParams.id);

    });

    routeDetailController中如上面提到的一样,注入了userService服务,在这里直接拿来用。

    3.创建list.html和detail.html页面,代码如下:

    <hr/>  

    <h3>Route : List.html(用户列表页面)</h3>  

    <ul>  

    <li ng-repeat="user in users">  

          <a href="http://m.cnblogs.com/142260/3817063.html?full=1#/list/{{ user.userId }}" target="_blank" rel="nofollow">

    </li>  

    </ul>

    <hr/>

     

    <h3>Route : detail.html(用户详细信息页面)</h3>  

    <h3>用户名:<span style="color: red;">{{userDetail.userName}}</span></h3>

    <div>

    <span>用户ID:{{userDetail.userId}}</span><span>用户名:{{userDetail.userName}}</span>

    </div>

    <div>

    用户简介:<span>{{userDetail.userInfo}}</span>

    </div>

    <div>

    <a href="http://m.cnblogs.com/142260/3817063.html?full=1#/list" target="_blank" rel="nofollow">返回</a>  

    </div>

    4. 路由局部刷新位置:

    <h1>AngularJS路由(Route) 示例</h1>  

    <div ng-view></div>


    4.10 NG动画效果


    4.10.1 NG动画效果简介

    NG动画效果,现在可以通过CSS3或者是JS来实现,如果是通过JS来实现的话,需要其他JS库(比如JQuery)来支持,实际上底层实现还是靠其他JS库,只是NG将其封装了,

    使其更易使用。

    NG动画效果包含以下几种:

        enter:元素添加到DOM中时执行动画;
        leave:元素从DOM删除时执行动画;
        move:移动元素时执行动画;
        beforeAddClass:在给元素添加CLASS之前执行动画;
        addClass:在给元素添加CLASS时执行动画;
        beforeRemoveClass:在给元素删除CLASS之前执行动画;
        removeClass:在给元素删除CLASS时执行动画。

    其相关参数为:

    var ngModule = angular.module('YourApp', ['ngAnimate']);

      demoApp.animation('.my-crazy-animation', function() {

    return {

       enter: function(element, done) {

      //run the animation here and call done when the animation is complete

            return function(cancelled) {

              //this (optional) function will be called when the animation

              //completes or when the animation is cancelled (the cancelled

              //flag will be set to true if cancelled).

            };

          },

          leave: function(element, done) { },

          move: function(element, done) { },

          //animation that can be triggered before the class is added

          beforeAddClass: function(element, className, done) { },

          //animation that can be triggered after the class is added

          addClass: function(element, className, done) { },

          //animation that can be triggered before the class is removed

          beforeRemoveClass: function(element, className, done) { },

          //animation that can be triggered after the class is removed

          removeClass: function(element, className, done) { }

        };

      });
    4.10.2 动画效果示例

    下面我们来看下DEMO中的例子(例10)。

    1.首先,我们在demoApp下定义一个动画效果,匹配CLASS:” .border-animation”

    /*定义动画*/

    demoApp.animation('.border-animation', function(){

    return{

    beforeAddClass : function (element, className, done) {

    $(element).stop().animate({

    'border-width':1

    },2000, function() {

    done();

    });

    },

    removeClass : function (element ,className ,done ) {

    $(element).stop().animate({

    'border-width':50

    },3000, function() {

    done();

    });

    }

    };

    });

    动画效果的含义就是:在匹配CLASS为border-animation的元素添加一个CLASS之前使其边框的宽度在2秒内变为1PX;并在其移除一个CLASS时使其边框的宽度在3秒内变为50PX。

    2. 视图中的代码如下(主要,其他相关样式请查看例子代码):

    <div class="border-animation" ng-show="testShow"></div>

    <a href="javascript:void(0);" target="_blank" rel="nofollow">

    ng-show为false时会为其加上“ng-hide“的CLASS; ng-show为true时会为其移除“ng-hide“的CLASS,从而触发动画效果。

    3.其他代码:

    demoApp.controller("test10Controller", function($scope, $animate){

    $scope.testShow = true;

    });


    5 功能演示

    略(详情请看AngularJS/demo WEB演示)


    6 AngularJS进阶


    6.1数据绑定原理研究

    Angular用户都想知道数据绑定是怎么实现的。你可能会看到各种各样的词汇:$watch、$apply、$digest、dirty-checking...它们是什么?它们是如何工作的呢?这里我想回答这些问题,其实它们在官方的文档里都已经回答了,但是我还是想把它们结合在一起来讲,但是我只是用一种简单的方法来讲解,如果要想了解技术细节,查看源代码。


    6.1.1 AngularJS扩展事件循环

    我们的浏览器一直在等待事件,比如用户交互。假如你点击一个按钮或者在输入框里输入东西,事件的回调函数就会在javascript解释器里执行,然后你就可以做任何DOM操作,等回调函数执行完毕时,浏览器就会相应地对DOM做出变化。(记住,这是个重要的概念),为了解释什么是context以及它如何工作,我们还需要解释更多的概念。


    6.1.2 $watch 队列

    每次你绑定一些东西到你的DOM上时你就会往$watch队列里插入一条$watch。想象一下$watch就是那个可以检测它监视的model里时候有变化的东西。例如你有如下的代码:

    /*View  index.html */

    User: <input type="text" ng-model="user" />

    Password: <input type="password" ng-model="pass" />

    在这里我们有个$scope.user,他被绑定在了第一个输入框上,还有个$scope.pass,它被绑定在了第二个输入框上,然后我们在$watch list里面加入两个$watch。

    再看下面的例子:

    /*Controller  controllers.js */

    app.controller('MainCtrl', function($scope) {

       $scope.foo = "Foo";

       $scope.world = "World";

    });

    /*View  index.html */

    Hello, {{ World }}

    这里,即便我们在$scope上添加了两个东西,但是只有一个绑定在了DOM上,因此在这里只生成了一个$watch。

    再看下面的例子:

    /*Controller  controllers.js */

    app.controller('MainCtrl', function($scope) {

      $scope.people = [...];

    });

    /*View  index.html */

    <ul>

      <li ng-repeat="person in people">

          {{person.name}} - {{person.age}}

      </li>

    </ul>

    这里又生成了多少个$watch呢?每个person有两个(一个name,一个age),然后ng-repeat又有一个,因此10个person一共是(2 * 10) 1,也就是说有21个$watch。

    因此,每一个绑定到了DOM上的数据都会生成一个$watch。

    那这写$watch是什么时候生成的呢?

    当我们的模版加载完毕时,也就是在linking阶段(Angular分为compile阶段和linking阶段),Angular解释器会寻找每个directive,然后生成每个需要的$watch。
    6.1.3 $digest循环

    还记得我前面提到的扩展的事件循环吗?当浏览器接收到可以被angular context处理的事件时,$digest循环就会触发。这个循环是由两个更小的循环组合起来的。一个处理evalAsync队列,另一个处理$watch队列。 这个是处理什么的呢?$digest将会遍历我们的$watch,然后询问:

    •嘿,$watch,你的值是什么?

    ◦是9。

    •好的,它改变过吗?

    ◦没有,先生。

    •(这个变量没变过,那下一个)

    •你呢,你的值是多少?

    ◦报告,是Foo。

    •刚才改变过没?

    ◦改变过,刚才是Bar。

    •(很好,我们有DOM需要更新了)

    •继续询问直到$watch队列都检查过。

    这就是所谓的dirty-checking。既然所有的$watch都检查完了,那就要问了:有没有$watch更新过?如果有至少一个更新过,这个循环就会再次触发,直到所有的$watch都没有变化。这样就能够保证每个model都已经不会再变化。记住如果循环超过10次的话,它将会抛出一个异常,防止无限循环。当$digest循环结束时,DOM相应地变化。

    例如:

    /*Controller  controllers.js */

    app.controller('MainCtrl', function() {

      $scope.name = "Foo";

      $scope.changeFoo = function() {

          $scope.name = "Bar";

      }

    });

    /*View  index.html */

    {{ name }}

    <button ng-click="changeFoo()">Change the name</button>

    这里我们有一个$watch因为ng-click不生成$watch(函数是不会变的)。

    我们可以看出ng的处理流程:

    •我们按下按钮;

    •浏览器接收到一个事件,进入angular context;

    •$digest循环开始执行,查询每个$watch是否变化;

    •由于监视$scope.name的$watch报告了变化,它会强制再执行一次$digest循环;

    •新的$digest循环没有检测到变化;

    •浏览器拿回控制权,更新与$scope.name新值相应部分的DOM。

    这里很重要的是每一个进入angular context的事件都会执行一个$digest循环,也就是说每次我们输入一个字母循环都会检查整个页面的所有$watch。


    6.1.4如何进入angular context

    谁决定什么事件进入angular context,而哪些又不进入呢?通过$apply!

    如果当事件触发时,你调用$apply,它会进入angular context,如果没有调用就不会进入。现在你可能会问:刚才的例子里我也没有调用$apply啊,为什么?Angular已经做了!因此你点击带有ng-click的元素时,时间就会被封装到一个$apply调用。如果你有一个ng-model="foo"的输入框,然后你敲一个f,事件就会这样调用$apply("foo = 'f';")。

    Angular什么时候不会自动为我们$apply呢?

    这是Angular新手共同的痛处。为什么我的jQuery不会更新我绑定的东西呢?因为jQuery没有调用$apply,事件没有进入angular context,$digest循环永远没有执行。

    我们来看一个有趣的例子:

    假设我们有下面这个directive和controller。

    /*Controller  app.js */

    app.directive('clickable', function() {

    return {

      restrict: "E",

      scope: {

        foo: '=',

        bar: '='

      },

      template: '<ul style="<li>{{foo}}</li><li>{{bar}}</li></ul>',

      link: function(scope, element, attrs) {

        element.bind('click', function() {

          scope.foo ;

          scope.bar ;

        });

      }

    }

    });

    app.controller('MainCtrl', function($scope) {

      $scope.foo = 0;

      $scope.bar = 0;

    });

    它将foo和bar从controller里绑定到一个list里面,每次点击这个元素的时候,foo和bar都会自增1。那我们点击元素的时候会发生什么呢?我们能看到更新吗?答案是否定的。因为点击事件是一个没有封装到$apply里面的常见的事件,这意味着我们会失去我们的计数吗?不会。

    真正的结果是:$scope确实改变了,但是没有强制$digest循环,监视foo 和bar的$watch没有执行。也就是说如果我们自己执行一次$apply那么这些$watch就会看见这些变化,然后根据需要更新DOM。

    执行$apply:

    element.bind('click', function() {

    scope.foo ;

      scope.bar ;

      scope.$apply();

    });

    $apply是我们的$scope(或者是direcvie里的link函数中的scope)的一个函数,调用它会强制一次$digest循环(除非当前正在执行循环,这种情况下会抛出一个异常,这是我们不需要在那里执行$apply的标志)。

    更好的使用$apply的方法:

    element.bind('click', function() {

      scope.$apply(function() {

          scope.foo ;

          scope.bar ;

      });

    })

    有什么不一样的?差别就是在第一个版本中,我们是在angular context的外面更新的数据,如果有发生错误,Angular永远不知道。很明显在这个像个小玩具的例子里面不会出什么大错,但是想象一下我们如果有个alert框显示错误给用户,然后我们有个第三方的库进行一个网络调用然后失败了,如果我们不把它封装进$apply里面,Angular永远不会知道失败了,alert框就永远不会弹出来了。

    因此,如果你想使用一个jQuery插件,并且要执行$digest循环来更新你的DOM的话,要确保你调用了$apply。

    有时候我想多说一句的是有些人在不得不调用$apply时会“感觉不妙”,因为他们会觉得他们做错了什么。其实不是这样的,Angular不是什么魔术师,他也不知道第三方库想要更新绑定的数据。


    6.1.5使用$watch来监视

    你已经知道了我们设置的任何绑定都有一个它自己的$watch,当需要时更新DOM,但是我们如果要自定义自己的watches呢?简单,来看个例子:

    /*Controller  app.js */

    app.controller('MainCtrl', function($scope) {

      $scope.name = "Angular";

      $scope.updated = -1;

      $scope.$watch('name', function() {

        $scope.updated ;

      });

    });

    /*View  index.html*/

    <body ng-controller="MainCtrl">

      <input ng-model="name" />

      Name updated: {{updated}} times.

    </body>

    这就是我们创造一个新的$watch的方法。第一个参数是一个字符串或者函数,在这里是只是一个字符串,就是我们要监视的变量的名字,在这里,$scope.name(注意我们只需要

    用name)。第二个参数是当$watch说我监视的表达式发生变化后要执行的。我们要知道的第一件事就是当controller执行到这个$watch时,它会立即执行一次,因此我们设置updated为-1。

    例子2:

    /*Controller  app.js */

    app.controller('MainCtrl', function($scope) {

      $scope.name = "Angular";

      $scope.updated = 0;

      $scope.$watch('name', function(newValue, oldValue) {

        if (newValue === oldValue) { return; } // AKA first run

        $scope.updated ;

      });

    });

    /*View  index.html*/

    <body ng-controller="MainCtrl">

      <input ng-model="name" />

      Name updated: {{updated}} times.

    </body>

    watch的第二个参数接受两个参数,新值和旧值。我们可以用他们来略过第一次的执行。通常你不需要略过第一次执行,但在这个例子里面你是需要的。

    例子3:

    /*Controller  app.js */

    app.controller('MainCtrl', function($scope) {

      $scope.user = { name: "Fox" };

      $scope.updated = 0;

      $scope.$watch('user', function(newValue, oldValue) {

        if (newValue === oldValue) { return; }

        $scope.updated ;

      });

    });

    /*View  index.html*/

    <body ng-controller="MainCtrl">

      <input ng-model="user.name" />

      Name updated: {{updated}} times.

    </body>

    我们想要监视$scope.user对象里的任何变化,和以前一样这里只是用一个对象来代替前面的字符串。

    呃?没用,为啥?因为$watch默认是比较两个对象所引用的是否相同,在例子1和2里面,每次更改$scope.name都会创建一个新的基本变量,因此$watch会执行,因为对这个变量的引用已经改变了。在上面的例子里,我们在监视$scope.user,当我们改变$scope.user.name时,对$scope.user的引用是不会改变的,我们只是每次创建了一个新的$scope.user.name,但是$scope.user永远是一样的。

    例子4:

    /*Controller  app.js */

    app.controller('MainCtrl', function($scope) {

      $scope.user = { name: "Fox" };

     

      $scope.updated = 0;

     

      $scope.$watch('user', function(newValue, oldValue) {

        if (newValue === oldValue) { return; }

        $scope.updated ;

      }, true  );

    });

    /*View  index.html*/

    <body ng-controller="MainCtrl">

      <input ng-model="user.name" />

      Name updated: {{updated}} times.

    </body>

    现在有用了吧!因为我们对$watch加入了第三个参数,它是一个bool类型的参数,表示的是我们比较的是对象的值而不是引用。由于当我们更新$scope.user.name时$scope.user也会改变,所以能够正确触发。


    6.1.6 总结

    我希望你们已经学会了在Angular中数据绑定是如何工作的。我猜想你的第一印象是dirty-checking很慢,好吧,其实是不对的。它像闪电般快。但是,如果你在一个模版里有2000-3000个watch,它会开始变慢。但是我觉得如果你达到这个数量级,就可以找个用户体验专家咨询一下了。

    无论如何,随着ECMAScript6的到来,在Angular未来的版本里我们将会有Object.observe那样会极大改善$digest循环的速度。


    6.2自定义指令详解

    angular的指令机制。angular通过指令的方式实现了HTML的扩展,增强后的HTML不仅长相焕然一新,同时也获得了很多强大的技能。更厉害的是,你还可以自定义指令,这就意味着HTML标签的范围可以扩展到无穷大。angular赋予了你造物主的能力。既然是作为angular的精华之一,相应的指令相关的知识也很多的。
    6.2.1指令的编译过程

      在开始自定义指令之前,我们有必要了解一下指令在框架中的执行流程:

    1.浏览器得到 HTML 字符串内容,解析得到 DOM 结构。

    2.ng 引入,把 DOM 结构扔给 $compile 函数处理:

    ① 找出 DOM 结构中有变量占位符;

    ② 匹配找出 DOM 中包含的所有指令引用;

    ③ 把指令关联到 DOM;

    ④ 关联到 DOM 的多个指令按权重排列;

    ⑤ 执行指令中的 compile 函数(改变 DOM 结构,返回 link 函数);

    ⑥ 得到的所有 link 函数组成一个列表作为 $compile 函数的返回。

    3. 执行 link 函数(连接模板的 scope)。

    这里注意区别一下$compile和compile,前者是ng内部的编译服务,后者是指令中的编译函数,两者发挥作用的范围不同。compile和link函数息息相关又有所区别,这个在后面会讲。了解执行流程对后面的理解会有帮助。

    在这里有些人可能会问,angular不就是一个js框架吗,怎么还能跟编译扯上呢,又不是像C 那样的高级语言。其实此编译非彼编译,ng编译的工作是解析指令、绑定监听器、替换模板中的变量等。因为工作方式很像高级语言编辑中的递归、堆栈过程,所以起名为编译,不要疑惑。
    6.2.2指令的使用方式及命名方法

      指令的几种使用方式如下:

        作为标签:<my-dir></my-dir>
        作为属性:<span my-dir="exp"></span>
        作为注释:<!-- directive: my-dir exp -->
        作为类名:<span class="my-dir: exp;"></span>

      其实常用的就是作为标签和属性,下面两种用法目前还没见过,感觉就是用来卖萌的,姑且留个印象。我们自定义的指令就是要支持这样的用法。

    关于自定义指令的命名,你可以随便怎么起名字都行,官方是推荐用[命名空间-指令名称]这样的方式,像ng-controller。不过你可千万不要用ng-前缀了,防止与系统自带的指令重名。另外一个需知道的地方,指令命名时用驼峰规则,使用时用-分割各单词。如:定义myDirective,使用时像这样:<my-directive>。


    6.2.3自定义指令的配置参数

    下面是定义一个标准指令的示例,可配置的参数包括以下部分:

    myModule.directive('namespaceDirectiveName', function factory(injectables) {

            var directiveDefinitionObject = {

                restrict: string,//指令的使用方式,包括标签,属性,类,注释

                priority: number,//指令执行的优先级

                template: string,//指令使用的模板,用HTML字符串的形式表示

                templateUrl: string,//从指定的url地址加载模板

                replace: bool,//是否用模板替换当前元素,若为false,则append在当前元素上

                transclude: bool,//是否将当前元素的内容转移到模板中

                scope: bool or object,//指定指令的作用域

            controller: function controllerConstructor($scope, $element, $attrs, $transclude){...},//定义与其他指令进行交互的接口函数

                require: string,//指定需要依赖的其他指令

    link: function postLink(scope, iElement, iAttrs) {...},//以编程的方式操作DOM,包

    括添加监听器等

                compile: function compile(tElement, tAttrs, transclude){

                    return: {

                        pre: function preLink(scope, iElement, iAttrs, controller){...},

                        post: function postLink(scope, iElement, iAttrs, controller){...}

                    }

                }//编程的方式修改DOM模板的副本,可以返回链接函数

            };

            return directiveDefinitionObject;

    });         

    看上去好复杂的样子,定义一个指令需要这么多步骤嘛?当然不是,你可以根据自己的需要来选择使用哪些参数。事实上priority和compile用的比较少,template和templateUrl又是互斥的,两者选其一即可。所以不必紧张,接下来分别学习一下这些参数:

    l 指令的表现配置参数:restrict、template、templateUrl、replace、transclude;

    l 指令的行为配置参数:compile和link;

    l 指令划分作用域配置参数:scope;

    l 指令间通信配置参数:controller和require。
    6.2.3指令的表现参数restrict等

    指令的表现配置参数:restrict、template、templateUrl、replace、transclude。

    我将先从一个简单的例子开始。

        例子的代码如下:

    var app = angular.module('MyApp', [], function(){console.log('here')});

    app.directive('sayHello',function(){

    return {

         restrict : 'E',

    template : '<div>hello</div>'

    };

    })         

    然后在页面中,我们就可以使用这个名为sayHello的指令了,它的作用就是输出一个hello单词。像这样使用:

    <say-hello></say-hello>         

    这样页面就会显示出hello了,看一下生成的代码:

    <say-hello>

    <div>hello</div>

    </say-hello>

       稍稍解释一下我们用到的两个参数,restirct用来指定指令的使用类型,其取值及含义如下:

    取值
        

    含义
        

    使用示例

    E
        

    标签
        

    <my-menu title=Products></my-menu>

    A
        

    属性
        

    <div my-menu=Products></div>

    C
        


        

    <div class="my-menu":Products></div>

    M
        

    注释
        

    <!--directive:my-menu Products-->

    默认值是A。也可以使用这些值的组合,如EA,EC等等。我们这里指定为E,那么它就可以像标签一样使用了。如果指定为A,我们使用起来应该像这样:

    <div say-hello></div>

    从生成的代码中,你也看到了template的作用,它就是描述你的指令长什么样子,这部分内容将出现在页面中,即该指令所在的模板中,既然是模板中,template的内容中也可以使用ng-modle等其他指令,就像在模板中使用一样。

    在上面生成的代码中,我们看到了<div>hello</div>外面还包着一层<say-hello>标签,如果我们不想要这一层多余的东西了,replace就派上用场了,在配置中将replace赋值为true,将得到如下结构:

    <div>hello</div>

       replace的作用正如其名,将指令标签替换为了temple中定义的内容。不写的话默认为false。

    上面的template未免也太简单了,如果你的模板HTML较复杂,如自定义一个ui组件指令,难道要拼接老长的字符串?当然不需要,此时只需用templateUrl便可解决问题。你可以将指令的模板单独命名为一个html文件,然后在指令定义中使用templateUrl指定好文件的路径即可,如:

    templateUrl : ‘helloTemplate.html’         

    系统会自动发一个http请求来获取到对应的模板内容。是不是很方便呢,你不用纠结于拼接字符串的烦恼了。如果你是一个追求完美的有考虑性能的工程师,可能会发问:那这样的话岂不是要牺牲一个http请求?这也不用担心,因为ng的模板还可以用另外一种方式定义,那就是使用<script>标签。使用起来如下:

    <script type="text/ng-template" id="helloTemplate.html">

         <div>hello</div>

    </script>        

     你可以把这段代码写在页面头部,这样就不必去请求它了。在实际项目中,你也可以将所有的模板内容集中在一个文件中,只加载一次,然后根据id来取用。

    接下来我们来看另一个比较有用的配置:transclude,定义是否将当前元素的内容转移到模板中。看解释有点抽象,不过亲手试试就很清楚了,看下面的代码(例06):

    app.directive('sayHello',function(){

    return {

         restrict : 'E',

    template : '<div>hello,<b ng-transclude></b>!</div>',

         replace : true,

          transclude : true

    };

    })         

    指定了transclude为true,并且template修改了一下,加了一个<b>标签,并在上面使用了ng-transclude指令,用来告诉指令把内容转移到的位置。那我们要转移的内容是什么呢?请看使用指令时的变化:

    <say-hello>美女</say-hello>

    内容是什么你也看到了哈~在运行的时候,美女将会被转移到<b>标签中,原来此配置的作用就是——乾坤大挪移!看效果:

    hello, 美女!

    这个还是很有用的,因为你定义的指令不可能老是那么简单,只有一个空标签。当你需要对指令中的内容进行处理时,此参数便大有可用。


    6.2.4指令的行为参数:compile和link

    6.2.3中简单介绍了自定义一个指令的几个简单参数,restrict、template、templateUrl、replace、transclude,这几个理解起来相对容易很多,因为它们只涉及到了表现,而没有涉及行为。我们继续学习ng自定义指令的几个重量级参数:compile和link

    l 理解compile和link

      不知大家有没有这样的感觉,自己定义指令的时候跟写jQuery插件有几分相似之处,都是先预先定义好页面结构及监听函数,然后在某个元素上调用一下,该元素便拥有了特殊的功能。区别在于,jQuery的侧重点是DOM操作,而ng的指令中除了可以进行DOM操作外,更注重的是数据和模板的绑定。jQuery插件在调用的时候才开始初始化,而ng指令在页面加载进来的时候就被编译服务($compile)初始化好了。

    在指令定义对象中,有compile和link两个参数,它们是做什么的呢?从字面意义上看,编译、链接,貌似太抽象了点。其实可大有内涵,为了在自定义指令的时候能正确使用它们,现在有必要了解一下ng是如何编译指令的。

    l 指令的解析流程详解

      我们知道ng框架会在页面载入完毕的时候,根据ng-app划定的作用域来调用$compile服务进行编译,这个$compile就像一个大总管一样,清点作用域内的DOM元素,看看哪些元素上使用了指令(如<div ng-modle=”m”></div>),或者哪些元素本身就是个指令(如<mydierc></mydirec>),或者使用了插值指令( {{}}也是一种指令,叫interpolation directive),$compile大总管会把清点好的财产做一个清单,然后根据这些指令的优先级(priority)排列一下,真是个细心的大总管哈~大总管还会根据指令中的配置参数(template,place,transclude等)转换DOM,让指令“初具人形”。

    然后就开始按顺序执行各指令的compile函数,注意此处的compile可不是大总管$compile,人家带着$是土豪,此处执行的compile函数是我们指令中配置的,compile函数中可以访问到DOM节点并进行操作,其主要职责就是进行DOM转换,每个compile函数执行完后都会返回一个link函数,这些link函数会被大总管汇合一下组合成一个合体后的link函数,为了好理解,我们可以把它想象成葫芦小金刚,就像是进行了这样的处理。

    //合体后的link函数

    function AB(){

      A(); //子link函数

      B(); //子link函数

    }  

    接下来进入link阶段,合体后的link函数被执行。所谓的链接,就是把view和scope链接起来。链接成啥样呢?就是我们熟悉的数据绑定,通过在DOM上注册监听器来动态修改scope中的数据,或者是使用$watchs监听 scope中的变量来修改DOM,从而建立双向绑定。由此也可以断定,葫芦小金刚可以访问到scope和DOM节点。

    不要忘了我们在定义指令中还配置着一个link参数呢,这么多link千万别搞混了。那这

    个link函数是干嘛的呢,我们不是有葫芦小金刚了嘛?那我告诉你,其实它是一个小三。此话怎讲?compile函数执行后返回link函数,但若没有配置compile函数呢?葫芦小金刚自然就不存在了。

    正房不在了,当然就轮到小三出马了,大总管$compile就把这里的link函数拿来执行。这就意味着,配置的link函数也可以访问到scope以及DOM节点。值得注意的是,compile函数通常是不会被配置的,因为我们定义一个指令的时候,大部分情况不会通过编程的方式进行DOM操作,而更多的是进行监听器的注册、数据的绑定。所以,小三名正言顺的被大总管宠爱。

    听完了大总管、葫芦小金刚和小三的故事,你是不是对指令的解析过程比较清晰了呢?不过细细推敲,你可能还是会觉得情节生硬,有些细节似乎还是没有透彻的明白,所以还需要再理解下面的知识点:

    l compile和link的区别

      其实在我看完官方文档后就一直有疑问,为什么监听器、数据绑定不能放在compile函数中,而偏偏要放在link函数中?为什么有了compile还需要link?就跟你质疑我编的故事一样,为什么最后小三被宠爱了?所以我们有必要探究一下,compile和link之间到底有什么区别。好,正房与小三的PK现在开始。

    首先是性能。举个例子:

    <ul>

      <li ng-repeat="a in array">

        <input ng-modle=”a.m” />

      </li>

    </ul>         

    我们的观察目标是ng-repeat指令。假设一个前提是不存在link。大总管$compile在编译这段代码时,会查找到ng-repeat,然后执行它的compile函数,compile函数根据array的长度复制出n个<li>标签。而复制出的<li>节点中还有<input>节点并且使用了ng-modle指令,所以compile还要扫描它并匹配指令,然后绑定监听器。每次循环都做如此多的工作。而更加糟糕的一点是,我们会在程序中向array中添加元素,此时页面上会实时更新DOM,每次有新元素进来,compile函数都把上面的步骤再走一遍,岂不是要累死了,这样性能必然不行。

    现在扔掉那个假设,在编译的时候compile就只管生成DOM的事,碰到需要绑定监听器的地方先存着,有几个存几个,最后把它们汇总成一个link函数,然后一并执行。这样就轻松多了,compile只需要执行一次,性能自然提升。

    另外一个区别是能力。

    尽管compile和link所做的事情差不多,但它们的能力范围还是不一样的。比如正房能管你的存款,小三就不能。小三能给你初恋的感觉,正房却不能。

    我们需要看一下compile函数和link函数的定义:

    function compile(tElement, tAttrs, transclude) { ... }

    function link(scope, iElement, iAttrs, controller) { ... }            

    这些参数都是通过依赖注入而得到的,可以按需声明使用。从名字也容易看出,两个函数各自的职责是什么,compile可以拿到transclude,允许你自己编程管理乾坤大挪移的行为。而link中可以拿到scope和controller,可以与scope进行数据绑定,与其他指令进行通信。两者虽然都可以拿到element,但是还是有区别的,看到各自的前缀了吧?compile拿到的是编译前的,是从template里拿过来的,而link拿到的是编译后的,已经与作用域建立了

    关联,这也正是link中可以进行数据绑定的原因。

      我暂时只能理解到这个程度了。实在不想理解这些知识的话,只要简单记住一个原则就行了:如果指令只进行DOM的修改,不进行数据绑定,那么配置在compile函数中,如果指令要进行数据绑定,那么配置在link函数中。
    6.2.5指令的划分作用域参数:scope

    我们在上面写了一个简单的<say-hello></say-hello>,能够跟美女打招呼。但是看看人家ng内置的指令,都是这么用的:ng-model=”m”,ng-repeat=”a in array”,不单单是作为属性,还可以赋值给它,与作用域中的一个变量绑定好,内容就可以动态变化了。假如我们的sayHello可以这样用:<say-hello speak=”content”>美女</say-hello>,把要对美女说的话写在一个变量content中,然后只要在controller中修改content的值,页面就可以显示对美女说的不同的话。这样就灵活多了,不至于见了美女只会说一句hello,然后就没有然后。

    为了实现这样的功能,我们需要使用scope参数,下面来介绍一下。

    使用scope为指令划分作用域

      顾名思义,scope肯定是跟作用域有关的一个参数,它的作用是描述指令与父作用域的关系,这个父作用域是指什么呢?想象一下我们使用指令的场景,页面结构应该是这个样子:

    <div ng-controller="testC">

        <say-hello speak="content">美女</say-hello>

    </div>  

    外层肯定会有一个controller,而在controller的定义中大体是这个样子:

    var app = angular.module('MyApp', [], function(){console.log('here')});

    app.controller('testC',function($scope){

    $scope.content = '今天天气真好!';

    }); 

    所谓sayHello的父作用域就是这个名叫testC的控制器所管辖的范围,指令与父作用域的关系可以有如下取值:

    取值
        

    说明

    false
        

    默认值。使用父作用域作为自己的作用域

    true
        

    新建一个作用域,该作用域继承父作用域

    javascript对象
        

    与父作用域隔离,并指定可以从父作用域访问的变量

    乍一看取值为false和true好像没什么区别,因为取值为true时会继承父作用域,即父作用域中的任何变量都可以访问到,效果跟直接使用父作用域差不多。但细细一想还是有区别的,有了自己的作用域后就可以在里面定义自己的东西,与跟父作用域混在一起是有本质上的区别。好比是父亲的钱你想花多少花多少,可你自己挣的钱父亲能花多少就不好说了。你若想看这两个作用域的区别,可以在link函数中打印出来看看,还记得link函数中可以访问到scope吧。

    最有用的还是取值为第三种,一个对象,可以用键值来显式的指明要从父作用域中使用属性的方式。当scope值为一个对象时,我们便建立了一个与父层隔离的作用域,不过也不是完全隔离,我们可以手工搭一座桥梁,并放行某些参数。我们要实现对美女说各种话就得靠这个。使用起来像这样:

    scope: {

            attributeName1: 'BINDING_STRATEGY',

            attributeName2: 'BINDING_STRATEGY',...

    }  

    键为属性名称,值为绑定策略。等等!啥叫绑定策略?最讨厌冒新名词却不解释的行为!别急,听我慢慢道来。

     

      先说属性名称吧,你是不是认为这个attributeName1就是父作用域中的某个变量名称?错!其实这个属性名称是指令自己的模板中要使用的一个名称,并不对应父作用域中的变量,稍后的例子中我们来说明。再来看绑定策略,它的取值按照如下的规则:

    符号
        

    说明
        

    举例

    @
        

    传递一个字符串作为属性的值
        

    str : ‘@string’

    =
        

    使用父作用域中的一个属性,绑定数据到指令的属性中
        

    name : ‘=username’

    &
        

    使用父作用域中的一个函数,可以在指令中调用
        

    getName : ‘&getUserName’

      总之就是用符号前缀来说明如何为指令传值。你肯定迫不及待要看例子了,我们结合例子看一下,小二,上栗子~

    举例说明

    我想要实现上面想像的跟美女多说点话的功能,即我们给sayHello指令加一个属性,通过给属性赋值来动态改变说话的内容 主要代码如下:

    app.controller('testC',function($scope){

       $scope.content = '今天天气真好!';

    });

    app.directive('sayHello',function(){

        return {

            restrict : 'E',

    template: '<div>hello,<b ng-transclude></b>,{{ cont }}</div>',

            replace : true,

            transclude : true,

            scope : {

     

                 cont : '=speak'

             }

        };

    });

    然后在模板中,我们如下使用指令:

    <div ng-controller="testC">

        <say-hello speak=" content ">美女</say-hello>

    </div>

    看看运行效果:

    美女今天天气真好!

      执行的流程是这样的:

      ① 指令被编译的时候会扫描到template中的{ {cont} },发现是一个表达式;

      ② 查找scope中的规则:通过speak与父作用域绑定,方式是传递父作用域中的属性;

      ③ speak与父作用域中的content属性绑定,找到它的值“今天天气真好!”;

      ④ 将content的值显示在模板中。

    这样我们说话的内容content就跟父作用域绑定到了一其,如果动态修改父作用域的content的值,页面上的内容就会跟着改变,正如你点击“换句话”所看到的一样。

      这个例子也太小儿科了吧!简单虽简单,但可以让我们理解清楚,为了检验你是不是真的明白了,可以思考一下如何修改指令定义,能让sayHello以如下两种方式使用:

    <span say-hello speak="content">美女</span>

    <span say-hello="content" >美女</span>

      答案我就不说了,简单的很。下面有更重要的事情要做,我们说好了要写一个真正能用的东西来着。接下来就结合所学到的东西来写一个折叠菜单,即点击可展开,再点击一次就收缩回去的菜单。

    控制器及指令的代码如下(例07):

    app.controller('testC',function($scope){

            $scope.title = '个人简介';

        $scope.text = '大家好,我是一名前端工程师,我正在研究AngularJs,欢迎大家与我交流';

    });

        app.directive('expander',function(){

            return {

                restrict : 'E',

                templateUrl : 'expanderTemp.html',

                replace : true,

                transclude : true,

                scope : {

                    mytitle : '=etitle'

                },

                link : function(scope,element,attris){

                    scope.showText = false;

                    scope.toggleText = function(){

                        scope.showText = ! scope.showText;

                    }

                }

            };

        });

    HTML中的代码如下:

     

    <script type="text/ng-template" id="expanderTemp.html">

        <div  class="mybox">

    <div class="mytitle" ng-click="toggleText()">

    {{mytitle}}

    </div>

    <div ng-transclude ng-show="showText">

    </div>

    </div>

    </script>

    <div ng-controller="testC">

        <expander etitle="title">{{text}}</expander>

    </div>

      还是比较容易看懂的,我只做一点必要的解释。首先我们定义模板的时候使用了ng的一种定义方式<script type=”text/ng-template”id="expanderTemp.html">,在指令中就可以用templateUrl根据这个id来找到模板。指令中的{{mytitle}}表达式由scope参数指定从etitle传递,etitle指向了父作用域中的title。为了实现点击标题能够展开收缩内容,我们把这部分逻辑放在了link函数中,link函数可以访问到指令的作用域,我们定义showText属性来表示内容部分的显隐,定义toggleText函数来进行控制,然后在模板中绑定好。 如果把showText和toggleText定义在controller中,作为$scope的属性呢?显然是不行的,这就是隔离作用域的意义所在,父作用域中的东西除了title之外通通被屏蔽。

    上面的例子中,scope参数使用了=号来指定获取属性的类型为父作用域的属性,如果我们想在指令中使用父作用域中的函数,使用&符号即可,是同样的原理。
    6.2.6指令间通信参数:controller和require

      使用指令来定义一个ui组件是个不错的想法,首先使用起来方便,只需要一个标签或者属性就可以了,其次是可复用性高,通过controller可以动态控制ui组件的内容,而且拥有双向绑定的能力。当我们想做的组件稍微复杂一点,就不是一个指令可以搞定的了,就需要指令与指令的协作才可以完成,这就需要进行指令间通信。

    想一下我们进行模块化开发的时候的原理,一个模块暴露(exports)对外的接口,另外一个模块引用(require)它,便可以使用它所提供的服务了。ng的指令间协作也是这个原理,这也正是自定义指令时controller参数和require参数的作用。

    controller参数用于定义指令对外提供的接口,它的写法如下:

     

    controller: function controllerConstructor($scope, $element, $attrs, $transclude)  

    它是一个构造器函数,将来可以构造出一个实例传给引用它的指令。为什么叫controller(控制器)呢?其实就是告诉引用它的指令,你可以控制我。至于可以控制那些东西呢,就需要在函数体中进行定义了。先看controller可以使用的参数,作用域、节点、节点的属性、节点内容的迁移,这些都可以通过依赖注入被传进来,所以你可以根据需要只写要用的参数。关于如何对外暴露接口,我们在下面的例子来说明。

    require参数便是用来指明需要依赖的其他指令,它的值是一个字符串,就是所依赖的指令的名字,这样框架就能按照你指定的名字来从对应的指令上面寻找定义好的controller了。不过还稍稍有点特别的地方,为了让框架寻找的时候更轻松些,我们可以在名字前面加个小小的前缀:^,表示从父节点上寻找,使用起来像这样:require : ‘^directiveName’,如果不加,$compile服务只会从节点本身寻找。另外还可以使用前缀:?,此前缀将告诉$compile服务,如果所需的controller没找到,不要抛出异常。

    所需要了解的知识点就这些,接下来是例子时间,依旧是从书上抄来的一个例子,我们要做的是一个手风琴菜单,就是多个折叠菜单并列在一起,此例子用来展示指令间的通信再合适不过。

    首先我们需要定义外层的一个结构,起名为accordion,代码如下:

    app.directive('accordion',function(){

            return {

                restrict : 'E',

                template : '<div ng-transclude></div>',

                replace : true,

                transclude : true,

    controller :function(){

                    var expanders = [];

                    this.gotOpended = function(selectedExpander){

                        angular.forEach(expanders,function(e){

                            if(selectedExpander != e){

                                e.showText = false;

                            }

                        });

                    }

                    this.addExpander = function(e){

                        expanders.push(e);

                    }

                }

            }

        });

    需要解释的只有controller中的代码,我们定义了一个折叠菜单数组expanders,并且通过this关键字来对外暴露接口,提供两个方法。gotOpended接受一个selectExpander参数用来修改数组中对应expander的showText属性值,从而实现对各个子菜单的显隐控制。addExpander方法对外提供向expanders数组增加元素的接口,这样在子菜单的指令中,便可以调用它把自身加入到accordion中。

    看一下我们的expander需要做怎样的修改呢:

    app.directive('expander',function(){

            return {

                restrict : 'E',

                templateUrl : 'expanderTemp.html',

                replace : true,

                transclude : true,

                require : '^?accordion',

                scope : {

                    title : '=etitle'

                },

     

                link : function(scope,element,attris,accordionController){

                    scope.showText = false;

                    accordionController.addExpander(scope);

                    scope.toggleText = function(){

                        scope.showText = ! scope.showText;

                        accordionController.gotOpended(scope);

                    }

                }

            };

        });

    首先使用require参数引入所需的accordion指令,添加?^前缀表示从父节点查找并且失败后不抛出异常。然后便可以在link函数中使用已经注入好的accordionController了,调用addExpander方法将自己的作用域作为参数传入,以供accordionController访问其属性。然

    后在toggleText方法中,除了要把自己的showText修改以外,还要调用accordionController的gotOpended方法通知父层指令把其他菜单给收缩起来。

    指令定义好后,我们就可以使用了,使用起来如下:

     

    <accordion>

    <expander ng-repeat="expander in expanders" etitle="expander.title">

    {{expander.text}}

    </expander>

    </accordion>  

    外层使用了accordion指令,内层使用expander指令,并且在expander上用ng-repeat循环输出子菜单。请注意这里遍历的数组expanders可不是accordion中定义的那个expanders,如果你这么认为了,说明还是对作用域不够了解。此expanders是ng-repeat的值,它是在外层controller中的,所以,在testC中,我们需要添加如下数据:

    $scope.expanders = [

                {title: '个人简介',

                 text: '大家好,我是一名前端工程师,我正在研究AngularJs,欢迎大家与我交流'},

                {title: '我的爱好',

                 text: 'LOL '},

                {title: '性格',

                 text: ' 我的性格就是无性格'}

            ];


    6.3 性能及调优
    6.3.1性能测试

    AnglarJS作为一款优秀的Web框架,可大大简化前端开发的负担。

    AnglarJS很棒,但当处理包含复杂数据结构的大型列表时,其运行速度就会非常慢。

    这是我们将核心管理页面迁移到AngularJS过程中遇到的问题。这些页面在显示500行数据时本应该工作顺畅,但首个方法的渲染时间竟花费了7秒,太可怕了。后来,我们发现了在实现过程中存在两个主要性能问题。一个与“ng-repeat ”指令有关,另一个与过滤器有关。

    AngularJS 中的ng-repeat在处理大型列表时,速度为什么会变慢?

    AngularJS中的ng-repeat在处理2500个以上的双向数据绑定时速度会变慢。这是由于AngularJS通过“dirty checking”函数来检测变化。每次检测都会花费时间,所以包含复杂数据结构的大型列表将降低你应用的运行速度。

    提高性能的先决条件

    时间记录指令

    为了测量一个列表渲染所花费的时间,我们写了一个简单的程序,通过使用“ng-repeat”的属性“$last”来记录时间。时间存放在TimeTracker服务中,这样时间记录就与服务器端的数据加载分开了。

    // Post repeat directive for logging the rendering time   

    angular.module('siApp.services').directive('postRepeatDirective',   

    ['$timeout', '$log',  'TimeTracker',   

      function($timeout, $log, TimeTracker) {  

        return function(scope, element, attrs) {  

          if (scope.$last){  

             $timeout(function(){  

                 var timeFinishedLoadingList = TimeTracker.reviewListLoaded();  

                 var ref = new Date(timeFinishedLoadingList);  

                 var end = new Date();  

                 $log.debug("## DOM rendering list took: " (end - ref) " ms");  

             });  

           }  

        };  

      }  

    ]);  

    // Use in HTML:   

    <tr ng-repeat="item in items" post-repeat-directive>…</tr>  

    Chrome开发者工具的时间轴(Timeline)属性

    在Chrome开发者工具的时间轴标签中,你可以看见事件、每秒内浏览器帧数和内存分配。“memory”工具用来检测内存泄漏,及页面所需的内存。当帧速率每秒低于30帧时就会出现页面闪烁问题。“frames”工具可帮助了解渲染性能,还可显示出一个JavaScript任务所花费的CPU时间。

    通过限制列表的大小进行基本的调优

    缓解该问题,最好的办法是限制所显示列表的大小。可通过分页、添加无限滚动条来实现。

    分页,我们可以使用AngularJS的“limitTo”过滤器(AngularJS1.1.4版本以后)和“startFrom”过滤器。可以通过限制显示列表的大小来减少渲染时间。这是减少渲染时间最高效的方法。


    6.3.2七大调优法则

    1.渲染没有数据绑定的列表

    这是最明显的解决方案,因为数据绑定是性能问题最可能的根源。如果你只想显示一次列表,并不需要更新、改变数据,放弃数据绑定是绝佳的办法。不过可惜的是,你会失去对数据的控制权,但除了该法,我们别无选择。

    2.不要使用内联方法计算数据

    为了在控制器中直接过滤列表,不要使用可获得过滤链接的方法。“ng-repeat”会评估每个表达式。在我们的案例中,“filteredItems()”返回过滤链接。如果评估过程很慢,它将迅速降低整个应用的速度。

     

    l <li ng-repeat="item in filteredItems()"> //这并不是一个好方法,因为要频繁地评估。   

    l <li ng-repeat="item in items"> //这是要采用的方法  

    3.使用两个列表(一个用来进行视图显示,一个作为数据源)

    将要显示的列表与总的数据列表分开,是非常有用的模型。你可以对一些过滤进行预处理,并将存于缓存中的链接应用到视图上。下面案例展示了基本实现过程。filteredLists变量保存着缓存中的链接,applyFilter方法来处理映射。

    /* Controller */  

    // Basic list    

    var items = [{name:"John", active:true }, {name:"Adam"}, {name:"Chris"}, {name:"Heather"}];    

    // Init displayedList   

    $scope.displayedItems = items;  

    // Filter Cache   

    var filteredLists['active'] = $filter('filter)(items, {"active" : true});  

    // Apply the filter   

    $scope.applyFilter = function(type) {  

        if (filteredLists.hasOwnProperty(type){ // Check if filter is cached   

           $scope.displayedItems = filteredLists[type];  

        } else {   

            /* Non cached filtering */  

        }  

    }  

    // Reset filter   

    $scope.resetFilter = function() {  

        $scope.displayedItems = items;  

    }  

    /* View */  

    <button ng-click="applyFilter('active')">Select active</button>  

    <ul><li ng-repeat="item in displayedItems">{{item.name}}<li></ul>  

    4.在其他模板中使用ng-if来代替ng-show

    如果你用指令、模板来渲染额外的信息,例如通过点击来显示列表项的详细信息,一定要使用  ng-if(AngularJSv. 1.1.5以后)。ng-if可阻止渲染(与ng-show相比)。所以其它DOM和数据绑定可根据需要进行评估。

    <li ng-repeat="item in items">  

     

       <p> {{ item.title }} </p>  

       <button ng-click="item.showDetails = !item.showDetails">Show details</buttons>  

       <div ng-if="item.showDetails">  

           {{item.details}}  

       </div>  

    </li>  

    5.不要使用ng-mouseenter、ng-mouseleave等指令

    使用内部指令,像ng-mouseenter,AngularJS会使你的页面闪烁。浏览器的帧速率通常低于每秒30帧。使用jQuery创建动画、鼠标悬浮效果可以解决该问题。确保将鼠标事件放入jQuery的.live()函数中。

    6.关于过滤的小提示:通过ng-show隐藏多余的元素

    对于长列表,使用过滤同样会减低工作效率,因为每个过滤都会创建一个原始列表的子链接。在很多情况下,数据没有变化,过滤结果也会保持不变。所以对数据列表进行预过滤,并根据情况将它应用到视图中,会大大节约处理时间。

    在ng-repeat指令中使用过滤器,每个过滤器会返回一个原始链接的子集。AngularJS 从DOM中移除多余元素(通过调用 $destroy),同时也会从$scope中移除他们。当过滤器的输入发生改变时,子集也会随着变化,元素必须进行重新链接,或着再调用$destroy。

    大部分情况下,这样做很好,但一旦用户经常过滤,或者列表非常巨大,不断的链接与

    销毁将影响性能。为了加快过滤的速度,你可以使用ng-show和ng-hide指令。在控制器中,进行过滤,并为每项添加一个属性。依靠该属性来触发ng-show。结果是,只为这些元素增加ng-hide类,来代替将它们移除子列表、$scope和DOM。

    触发ng-show的方法之一是使用表达式语法。ng-show的值由表达式语法来确定。可以看下面的例子:

    <input ng-model="query"></input>  

    <li ng-repeat="item in items" ng-show="([item.name] | filter:query).length"> {{item.name}} </li>

    <span style="font-size: 14px; line-height: 24px; font-family:; white-space: normal;"></span>

    7.关于过滤的小提示:防抖动输入

    解决第6点提出的持续过滤问题的另一个方法是防抖动用户输入。例如,如果用户输入一个搜索关键词,只当用户停止输入后,过滤器才会被激活。使用该防抖动服务的一个很好的解决方案请见: http://jsfiddle.net/Warspawn/6K7Kd/。将它应用到你的视图及控制器中,如下所示:

    /* Controller */  

    // Watch the queryInput and debounce the filtering by 350 ms.   

    $scope.$watch('queryInput', function(newValue, oldValue) {  

        if (newValue === oldValue) { return; }  

        $debounce(applyQuery, 350);  

    });  

    var applyQuery = function() {   

        $scope.filter.query = $scope.query;  

    };    

    /* View */  

    <input ng-model="queryInput"/>  

    <li ng-repeat= item in items | filter:filter.query>{{ item.title }} </li>

     
    7 总结

    angular上手比较难,初学者(特别是习惯了使用JQuery的人)可能不太适应其语法以及思想。随着对ng探索的一步步深入,也确实感觉到了这一点,尤其是框架内部的某些执行机制。


    7.1页面效果

     ng-show ng-hide 无动画效果问题
    7.2委派事件(代理事件)
    7.2.1 NG循环及事件绑定

    <ul>

      <li ng-repeat="a in array">

        <input ng-modle=”a.m” />

      </li>

    </ul>

    Ng会根据array的长度复制出n个<li>标签。而复制出的<li>节点中还有<input>节点并且使用了ng-modle指令,所以ng会对所有的<input>绑定监听器(事件)。如果array很大,就会绑定太多的事件,性能出现问题。


    7.2.2 jQuery委派事件
     

    从jQuery1.7开始,提供了.on()附加事件处理程序。

    .on( events [, selector ] [, data ], handler(eventObject) )

    参数Selector为一个选择器字符串,用于过滤出被选中的元素中能触发事件的后代元素。如果选择器是 null 或者忽略了该选择器,那么被选中的元素总是能触发事件。

    如果省略selector或者是null,那么事件处理程序被称为直接事件 或者 直接绑定事件 。每次选中的元素触发事件时,就会执行处理程序,不管它直接绑定在元素上,还是从后代(内部)元素冒泡到该元素的。

    当提供selector参数时,事件处理程序是指为委派事件(代理事件)。事件不会在直接绑定的元素上触发,但当selector参数选择器匹配到后代(内部元素)的时候,事件处理函数才会被触发。jQuery 会从 event target 开始向上层元素(例如,由最内层元素到最外层元素)开始冒泡,并且在传播路径上所有绑定了相同事件的元素若满足匹配的选择器,那么这些元素上的事件也会被触发。

    委托事件有两个优势:他们能在后代元素添加到文档后,可以处理这些事件;代理事件的另一个好处就是,当需要监视很多元素的时候,代理事件的开销更小。

    例如,在一个表格的 tbody 中含有 1,000 行,下面这个例子会为这 1,000 元素绑定事

    $("#dataTable tbody tr").on("click", function(event){ alert($(this).text());});

    委派事件的方法只有一个元素的事件处理程序,tbody,并且事件只会向上冒泡一层(从被点击的tr 到 tbody ):

    $("#dataTable tbody").on("click", "tr", function(event){  alert($(this).text());});

    许多委派的事件处理程序绑定到 document 树的顶层附近,可以降低性能。每次发生事件时,jQuery 需要比较从 event target(目标元素) 开始到文档顶部的路径中每一个元素上所有该类型的事件。为了获得更好的性能,在绑定代理事件时,绑定的元素最好尽可能的靠近目标元素。避免在大型文档中,过多的在 document 或 document.body 上添加代理事件。

    展开全文
  • 全面掌握前端框架AngularJS

    千次阅读 2019-11-26 15:35:28
    AngularJS AngularJS 通过新的属性和表达式扩展了 HTML。 AngularJS 可以构建一个单一页面应用程序(SPAs:Single Page Applications)。 AngularJS 学习起来非常简单。 AngularJS 实例 <!DOCTYPE html>...

    整理自菜鸟教程

     

    AngularJS

    AngularJS 通过新的属性和表达式扩展了 HTML。

    AngularJS 可以构建一个单一页面应用程序(SPAs:Single Page Applications)。

    AngularJS 学习起来非常简单。

     

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="">
      <p>名字 : <input type="text" ng-model="name"></p>
      <h1>Hello {{name}}</h1>
    </div>

    </body>
    </html>

     

    AngularJS 历史

    AngularJS 是比较新的技术,版本 1.0 是在 2012 年发布的。

    AngularJS 是由 Google 的员工 Miško Hevery 从 2009 年开始着手开发。

    这是一个非常好的构想,该项目目前已由 Google 正式支持,有一个全职的开发团队继续开发和维护这个库。

     

    AngularJS 简介


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

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


    AngularJS 是一个 JavaScript 框架

    AngularJS 是一个 JavaScript 框架。它是一个以 JavaScript 编写的库。

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

    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>

     

    建议把脚本放在 <body> 元素的底部。
    这会提高网页加载速度,因为 HTML 加载不受制于脚本加载。

     


    AngularJS 扩展了 HTML

    AngularJS 通过 ng-directives 扩展了 HTML。

    ng-app 指令定义一个 AngularJS 应用程序。

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

    ng-bind 指令把应用程序数据绑定到 HTML 视图。

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="">
      <p>名字 : <input type="text" ng-model="name"></p>
      <h1>Hello {{name}}</h1>
    </div>

    </body>
    </html>

     

    实例讲解:

    当网页加载完毕,AngularJS 自动开启。

    ng-app 指令告诉 AngularJS,<div> 元素是 AngularJS 应用程序 的"所有者"。

    ng-model 指令把输入域的值绑定到应用程序变量 name

    ng-bind 指令把应用程序变量 name 绑定到某个段落的 innerHTML。

     

    如果您移除了 ng-app 指令,HTML 将直接把表达式显示出来,不会去计算表达式的结果。


    什么是 AngularJS?

    AngularJS 使得开发现代的单一页面应用程序(SPAs:Single Page Applications)变得更加容易。

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

    AngularJS 指令

    正如您所看到的,AngularJS 指令是以 ng 作为前缀的 HTML 属性。

    ng-init 指令初始化 AngularJS 应用程序变量。

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body>

    <div ng-app="" ng-init="firstName='John'">

    <p>姓名为 <span ng-bind="firstName"></span></p>

    </div>

    </body>
    </html>

     

    HTML5 允许扩展的(自制的)属性,以 data- 开头。
    AngularJS 属性以 ng- 开头,但是您可以使用 data-ng- 来让网页对 HTML5 有效。

     

    带有有效的 HTML5:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body>

    <div data-ng-app="" data-ng-init="firstName='John'">

    <p>姓名为 <span data-ng-bind="firstName"></span></p>

    </div>
    </body>
    </html>

     

     


    AngularJS 表达式

    AngularJS 表达式写在双大括号内:{{ expression }}

    AngularJS 表达式把数据绑定到 HTML,这与 ng-bind 指令有异曲同工之妙。

    AngularJS 将在表达式书写的位置"输出"数据。

    AngularJS 表达式 很像 JavaScript 表达式:它们可以包含文字、运算符和变量。

    实例 {{ 5 + 5 }} 或 {{ firstName + " " + lastName }}

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body>

    <div ng-app="">
      <p>我的第一个表达式: {{ 5 + 5 }}</p>
    </div>

    </body>
    </html>

     


    AngularJS 应用

    AngularJS 模块(Module) 定义了 AngularJS 应用。

    AngularJS 控制器(Controller) 用于控制 AngularJS 应用。

    ng-app指令指明了应用, ng-controller 指明了控制器。

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body>

    <p>尝试修改以下表单。</p>

    <div ng-app="myApp" ng-controller="myCtrl">

    名: <input type="text" ng-model="firstName"><br>
    姓: <input type="text" ng-model="lastName"><br>
    <br>
    姓名: {{firstName + " " + lastName}}

    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function($scope) {
        $scope.firstName= "John";
        $scope.lastName= "Doe";
    });
    </script>

    </body>
    </html>

     

    AngularJS 模块定义应用:

    AngularJS 模块

    var app = angular.module('myApp', []);

    AngularJS 控制器控制应用:

    AngularJS 控制器

    app.controller('myCtrl', function($scope) { $scope.firstName= "John"; $scope.lastName= "Doe"; });

    在接下来的教程中你将学习到更多的应用和模块的知识。


    在 Cloud Studio 中使用 AngularJS

    • step1:访问 Cloud Studio,注册/登录账户。

    • step2:在右侧的运行环境菜单选择:"ubuntu"

    • step3:在左侧代码目录中新建 html 目录,编写你的 HTML 代码,例如 index.html

    • step4:在 index.html 文件的中粘贴如下代码、来引入 AngularJS:

      <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    • step5:在终端中输入命令sudo vim /etc/nginx/site-enable/default。将配置文件红框部分修改为如下图所示,然后输入命令:sudo nginx restart 重启 nginx 服务( nginx 安装完成并启动后默认会监听80端口。我们需要将 nginx 的站点目录以及监听的端口号改为我们需要的)

    • step6:点击最右侧的【访问链接】选项卡,在访问链接面板中填写端口号为:8080(和刚才 nginx 配置文件中的端口号一致),点击创建链接,即可点击生成的链接访问我们刚刚编写的代码,查看 AngularJS 效果。

     

    AngularJS 表达式


    AngularJS 使用 表达式 把数据绑定到 HTML。


    AngularJS 表达式

    AngularJS 表达式写在双大括号内:{{ expression }}

    AngularJS 表达式把数据绑定到 HTML,这与 ng-bind 指令有异曲同工之妙。

    AngularJS 将在表达式书写的位置"输出"数据。

    AngularJS 表达式 很像 JavaScript 表达式:它们可以包含文字、运算符和变量。

    实例 {{ 5 + 5 }} 或 {{ firstName + " " + lastName }}

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body>

    <div ng-app>
    <p>我的第一个表达式: {{ 5 + 5 }}</p>
    </div>

    </body>
    </html>

     


    AngularJS 数字

    AngularJS 数字就像 JavaScript 数字:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body>

    <div ng-app="" ng-init="quantity=1;cost=5">
    <p>总价: {{ quantity * cost }}</p>
    </div>

    </body>
    </html>

    div ng-app="" ng-init="quantity=1;cost=5"> <p>总价: {{ quantity * cost }}</p> </div>

     

    使用 ng-bind 的相同实例:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body>

    <div ng-app="" ng-init="quantity=1;cost=5">
    <p>总价: <span ng-bind="quantity * cost"></span></p>
    </div>

    </body>
    </html>

    使用 ng-init 不是很常见。您将在控制器一章中学习到一个更好的初始化数据的方式。


     

    AngularJS 字符串

    AngularJS 字符串就像 JavaScript 字符串:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body>

    <div ng-app="" ng-init="firstName='John';lastName='Doe'">

    <p>姓名: {{ firstName + " " + lastName }}</p>

    </div>

    </body>
    </html>

     

    使用 ng-bind 的相同实例:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body>

    <div ng-app="" ng-init="firstName='John';lastName='Doe'">

    <p>姓名: <span ng-bind="firstName + ' ' + lastName"></span></p>

    </div>

    </body>
    </html>

     

     


    AngularJS 对象

    AngularJS 对象就像 JavaScript 对象:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body>

    <div ng-app="" ng-init="person={firstName:'John',lastName:'Doe'}">

    <p>姓为 {{ person.lastName }}</p>

    </div>

    </body>
    </html>

     

    使用 ng-bind 的相同实例:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body>

    <div ng-app="" ng-init="person={firstName:'John',lastName:'Doe'}">

    <p>姓为 <span ng-bind="person.lastName"></span></p>

    </div>

    </body>
    </html>

     

     


    AngularJS 数组

    AngularJS 数组就像 JavaScript 数组:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body>

    <div ng-app="" ng-init="points=[1,15,19,2,40]">

    <p>第三个值为 {{ points[2] }}</p>

    </div>

    </body>
    </html>

     

    使用 ng-bind 的相同实例:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body>

    <div ng-app="" ng-init="points=[1,15,19,2,40]">

    <p>第三个值为 <span ng-bind="points[2]"></span></p>

    </div>

    </body>
    </html>

     


    AngularJS 表达式 与 JavaScript 表达式

    类似于 JavaScript 表达式,AngularJS 表达式可以包含字母,操作符,变量。

    与 JavaScript 表达式不同,AngularJS 表达式可以写在 HTML 中。

    与 JavaScript 表达式不同,AngularJS 表达式不支持条件判断,循环及异常。

    与 JavaScript 表达式不同,AngularJS 表达式支持过滤器。

     

    AngularJS 指令


    AngularJS 通过被称为 指令 的新属性来扩展 HTML。

    AngularJS 通过内置的指令来为应用添加功能。

    AngularJS 允许你自定义指令。


    AngularJS 指令

    AngularJS 指令是扩展的 HTML 属性,带有前缀 ng-

    ng-app 指令初始化一个 AngularJS 应用程序。

    ng-init 指令初始化应用程序数据。

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

     

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body>

    <div ng-app="" ng-init="firstName='John'">

    <p>在输入框中尝试输入:</p>
    <p>姓名: <input type="text" ng-model="firstName"></p>
    <p>你输入的为: {{ firstName }}</p>

    </div>

    </body>
    </html>

     

    ng-app 指令告诉 AngularJS,<div> 元素是 AngularJS 应用程序 的"所有者"。

    数据绑定

    上面实例中的 {{ firstName }} 表达式是一个 AngularJS 数据绑定表达式。

    AngularJS 中的数据绑定,同步了 AngularJS 表达式与 AngularJS 数据。

    {{ firstName }} 是通过 ng-model="firstName" 进行同步。

    在下一个实例中,两个文本域是通过两个 ng-model 指令同步的:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body>

    <div data-ng-app="" data-ng-init="quantity=1;price=5">

    <h2>价格计算器</h2>

    数量: <input type="number" ng-model="quantity">
    价格: <input type="number" ng-model="price">

    <p><b>总价:</b> {{quantity * price}}</p>

    </div>

    </body>
    </html>

     

     

    重复 HTML 元素



    ng-repeat 指令会重复一个 HTML 元素:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body>

    <div data-ng-app="" data-ng-init="names=['Jani','Hege','Kai']">
      <p>使用 ng-repeat 来循环数组</p>
      <ul>
        <li data-ng-repeat="x in names">
          {{ x }}
        </li>
      </ul>
    </div>

    </body>
    </html>

     

    ng-repeat 指令用在一个对象数组上:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body>

    <div ng-app="" ng-init="names=[
    {name:'Jani',country:'Norway'},
    {name:'Hege',country:'Sweden'},
    {name:'Kai',country:'Denmark'}]">

    <p>循环对象:</p>
    <ul>
      <li ng-repeat="x in names">
      {{ x.name + ', ' + x.country }}</li>
    </ul>

    </div>

    </body>
    </html>

     

    AngularJS 完美支持数据库的 CRUD(增加Create、读取Read、更新Update、删除Delete)应用程序。
    把实例中的对象想象成数据库中的记录。


    ng-app 指令

    ng-app 指令定义了 AngularJS 应用程序的 根元素

    ng-app 指令在网页加载完毕时会自动引导(自动初始化)应用程序。

    稍后您将学习到 ng-app 如何通过一个值(比如 ng-app="myModule")连接到代码模块。


    ng-init 指令

    ng-init 指令为 AngularJS 应用程序定义了 初始值

    通常情况下,不使用 ng-init。您将使用一个控制器或模块来代替它。

    稍后您将学习更多有关控制器和模块的知识。


    ng-model 指令

    ng-model 指令 绑定 HTML 元素 到应用程序数据。

    ng-model 指令也可以:

    • 为应用程序数据提供类型验证(number、email、required)。
    • 为应用程序数据提供状态(invalid、dirty、touched、error)。
    • 为 HTML 元素提供 CSS 类。
    • 绑定 HTML 元素到 HTML 表单。

    ng-repeat 指令

    ng-repeat 指令对于集合中(数组中)的每个项会 克隆一次 HTML 元素

     


    创建自定义的指令

    除了 AngularJS 内置的指令外,我们还可以创建自定义指令。

    你可以使用 .directive 函数来添加自定义的指令。

    要调用自定义指令,HTML 元素上需要添加自定义指令名。

    使用驼峰法来命名一个指令, runoobDirective, 但在使用它时需要以 - 分割, runoob-directive:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body ng-app="myApp">

    <runoob-directive></runoob-directive>

    <script>
    var app = angular.module("myApp", []);
    app.directive("runoobDirective", function() {
        return {
            template : "<h1>自定义指令!</h1>"
        };
    });
    </script>

    </body>
    </html>

     

    你可以通过以下方式来调用指令:

    • 元素名
    • 属性
    • 类名
    • 注释

    以下实例方式也能输出同样结果:

    元素名

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body ng-app="myApp">

    <runoob-directive></runoob-directive>

    <script>
    var app = angular.module("myApp", []);
    app.directive("runoobDirective", function() {
        return {
            template : "<h1>自定义指令!</h1>"
        };
    });
    </script>

    </body>
    </html>

     

    属性

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body ng-app="myApp">

    <div runoob-directive></div>

    <script>
    var app = angular.module("myApp", []);
    app.directive("runoobDirective", function() {
        return {
            template : "<h1>自定义指令!</h1>"
        };
    });
    </script>

    </body>
    </html>

     

    类名

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body ng-app="myApp">

    <div class="runoob-directive"></div>

    <script>
    var app = angular.module("myApp", []);
    app.directive("runoobDirective", function() {
        return {
            restrict : "C",
            template : "<h1>自定义指令!</h1>"
        };
    });
    </script>

    <p><strong>注意:</strong> 你必须设置 <b>restrict</b> 的值为 "C" 才能通过类名来调用指令。</p>

    </body>
    </html>

     

    注释

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body ng-app="myApp">

    <!-- directive: runoob-directive -->

    <script>
    var app = angular.module("myApp", []);
    app.directive("runoobDirective", function() {
        return {
            restrict : "M",
            replace : true,
            template : "<h1>自定义指令!</h1>"
        };
    });
    </script>

    <p><strong>注意:</strong> 我们需要在该实例添加 <strong>replace</strong> 属性, 否则评论是不可见的。</p>

    <p><strong>注意:</strong> 你必须设置 <b>restrict</b> 的值为 "M" 才能通过注释来调用指令。</p>

    </body>
    </html>

    !-- directive: runoob-directive -->

     

    限制使用

    你可以限制你的指令只能通过特定的方式来调用。

    实例

    通过添加 restrict 属性,并设置值为 "A", 来设置指令只能通过属性的方式来调用:

    <!DOCTYPE html>
    <html><head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body ng-app="myApp">

    <runoob-directive></runoob-directive>

    <div runoob-directive></div>

    <script>
    var app = angular.module("myApp", []);
    app.directive("runoobDirective", function() {
        return {
            restrict : "A",
            template : "<h1>自定义指令!</h1>"
        };
    });
    </script>

    <p><strong>注意:</strong> 通过设置 <strong>restrict</strong> 属性值为 "A" 来设置指令只能通过 HTML 元素的属性来调用。</p>

    </body>
    </html>

     

    restrict 值可以是以下几种:

    • E 作为元素名使用
    • A 作为属性使用
    • C 作为类名使用
    • M 作为注释使用

    restrict 默认值为 EA, 即可以通过元素名和属性名来调用指令。

     

    AngularJS ng-model 指令


    ng-model 指令用于绑定应用程序数据到 HTML 控制器(input, select, textarea)的值。


    ng-model 指令

    ng-model 指令可以将输入域的值与 AngularJS 创建的变量绑定。

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body>

    <div ng-app="myApp" ng-controller="myCtrl">
    名字: <input ng-model="name">
    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function($scope) {
        $scope.name = "John Doe";
    });
    </script>

    <p>使用 ng-model 指令来绑定输入域的值到控制器的属性。</p>

    </body>
    </html>

     


    双向绑定

    双向绑定,在修改输入域的值时, AngularJS 属性的值也将修改:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body>

    <div ng-app="myApp" ng-controller="myCtrl">
    名字: <input ng-model="name">
    <h1>你输入了: {{name}}</h1>
    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function($scope) {
        $scope.name = "John Doe";
    });
    </script>

    <p>修改输入框的值,标题的名字也会相应修改。</p>

    </body>
    </html>

     


    验证用户输入

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body>

    <form ng-app="" name="myForm">
        Email:
        <input type="email" name="myAddress" ng-model="text">
        <span ng-show="myForm.myAddress.$error.email">不是一个合法的邮箱地址</span>
    </form>

    <p>在输入框中输入你的邮箱地址,如果不是一个合法的邮箱地址,会弹出提示信息。</p>

    </body>
    </html>

     

    以上实例中,提示信息会在 ng-show 属性返回 true 的情况下显示。


    应用状态

    ng-model 指令可以为应用数据提供状态值(invalid, dirty, touched, error):

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body>

    <form ng-app="" name="myForm" ng-init="myText = 'test@runoob.com'">

    Email:
    <input type="email" name="myAddress" ng-model="myText" required>
    <p>编辑邮箱地址,查看状态的改变。</p>
    <h1>状态</h1>
    <p>Valid: {{myForm.myAddress.$valid}} (如果输入的值是合法的则为 true)。</p>
    <p>Dirty: {{myForm.myAddress.$dirty}} (如果值改变则为 true)。</p>
    <p>Touched: {{myForm.myAddress.$touched}} (如果通过触屏点击则为 true)。</p>

    </form>

    </body>
    </html>

     


    CSS 类

    ng-model 指令基于它们的状态为 HTML 元素提供了 CSS 类:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    <style>
    input.ng-invalid {
        background-color: lightblue;
    }
    </style>
    </head>
    <body>

    <form ng-app="" name="myForm">
        输入你的名字:
        <input name="myName" ng-model="myText" required>
    </form>

    <p>编辑文本域,不同状态背景颜色会发生变化。</p>
    <p>文本域添加了 required 属性,该值是必须的,如果为空则是不合法的。</p>

    </body>
    </html>

     

    ng-model 指令根据表单域的状态添加/移除以下类:

    • ng-empty
    • ng-not-empty
    • ng-touched
    • ng-untouched
    • ng-valid
    • ng-invalid
    • ng-dirty
    • ng-pending
    • ng-pristine

     

    AngularJS Scope(作用域)


    Scope(作用域) 是应用在 HTML (视图) 和 JavaScript (控制器)之间的纽带。

    Scope 是一个对象,有可用的方法和属性。

    Scope 可应用在视图和控制器上。


    如何使用 Scope

    当你在 AngularJS 创建控制器时,你可以将 $scope 对象当作一个参数传递:

    AngularJS 实例

    控制器中的属性对应了视图上的属性:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="myCtrl">

    <h1>{{carname}}</h1>

    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function($scope) {
        $scope.carname = "Volvo";
    });
    </script>

    <p>控制器中创建一个属性名 "carname",对应了视图中使用 {{ }} 中的名称。</p>

    </body>
    </html>

     

    当在控制器中添加 $scope 对象时,视图 (HTML) 可以获取了这些属性。

    视图中,你不需要添加 $scope 前缀, 只需要添加属性名即可,如: {{carname}}


    Scope 概述

    AngularJS 应用组成如下:

    • View(视图), 即 HTML。
    • Model(模型), 当前视图中可用的数据。
    • Controller(控制器), 即 JavaScript 函数,可以添加或修改属性。

    scope 是模型。

    scope 是一个 JavaScript 对象,带有属性和方法,这些属性和方法可以在视图和控制器中使用。

    AngularJS 实例

    如果你修改了视图,模型和控制器也会相应更新:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="myCtrl">
        <input ng-model="name">
        <h1>{{greeting}}</h1>
        <button ng-click='sayHello()'>点我</button>    
    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function($scope) {
        $scope.name = "Runoob";
        $scope.sayHello = function() {
            $scope.greeting = 'Hello ' + $scope.name + '!';
        };
    });
    </script>

    <p>当你修改输入框中的值时,会影响到模型(model),当然也会影响到控制器对应的属性值。</p>

    </body>
    </html>

     


    Scope 作用范围

    了解你当前使用的 scope 是非常重要的。

    在以上两个实例中,只有一个作用域 scope,所以处理起来比较简单,但在大型项目中, HTML DOM 中有多个作用域,这时你就需要知道你使用的 scope 对应的作用域是哪一个。

    AngularJS 实例

    当我们使用 ng-repeat 指令时,每个重复项都访问了当前的重复对象:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="myCtrl">

    <ul>
        <li ng-repeat="x in names">{{x}}</li>
    </ul>

    </div>

    <script>
    var app = angular.module('myApp', []);

    app.controller('myCtrl', function($scope) {
        $scope.names = ["Emil", "Tobias", "Linus"];
    });
    </script>
        
    </body>
    </html>

     

    每个 <li> 元素可以访问当前的重复对象,这里对应的是一个字符串, 并使用变量 x 表示。


    根作用域

    所有的应用都有一个 $rootScope,它可以作用在 ng-app 指令包含的所有 HTML 元素中。

    $rootScope 可作用于整个应用中。是各个 controller 中 scope 的桥梁。用 rootscope 定义的值,可以在各个 controller 中使用。

    AngularJS 实例

    创建控制器时,将 $rootScope 作为参数传递,可在应用中使用:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="myCtrl">

    <h1>姓氏为 {{lastname}} 家族成员:</h1>

    <ul>
        <li ng-repeat="x in names">{{x}} {{lastname}}</li>
    </ul>

    </div>

    <script>
    var app = angular.module('myApp', []);

    app.controller('myCtrl', function($scope, $rootScope) {
        $scope.names = ["Emil", "Tobias", "Linus"];
        $rootScope.lastname = "Refsnes";
    });
    </script>

    <p>注意 $rootScope 在循环对象内外都可以访问。</p>

    </body>
    </html>

     

    AngularJS 控制器


     AngularJS 控制器 控制 AngularJS 应用程序的数据。

     AngularJS 控制器是常规的 JavaScript 对象


    AngularJS 控制器

    AngularJS 应用程序被控制器控制。

    ng-controller 指令定义了应用程序控制器。

    控制器是 JavaScript 对象,由标准的 JavaScript 对象的构造函数 创建。

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>

    <body>

    <div ng-app="myApp" ng-controller="myCtrl">

    名:  <input type="text" ng-model="firstName"><br>
    姓:  <input type="text" ng-model="lastName"><br>
    <br>
    姓名: {{firstName + " " + lastName}}

    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function($scope) {
        $scope.firstName = "John";
        $scope.lastName = "Doe";
    });
    </script>

    </body>
    </html>

     

    应用解析:

    AngularJS 应用程序由 ng-app 定义。应用程序在 <div> 内运行。

    ng-controller="myCtrl" 属性是一个 AngularJS 指令。用于定义一个控制器。

    myCtrl 函数是一个 JavaScript 函数。

    AngularJS 使用$scope 对象来调用控制器。

    在 AngularJS 中, $scope 是一个应用对象(属于应用变量和函数)。

    控制器的 $scope (相当于作用域、控制范围)用来保存AngularJS Model(模型)的对象。

    控制器在作用域中创建了两个属性 (firstName 和 lastName)。

    ng-model 指令绑定输入域到控制器的属性(firstName 和 lastName)。


    控制器方法

    上面的实例演示了一个带有 lastName 和 firstName 这两个属性的控制器对象。

    控制器也可以有方法(变量和函数):

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="personCtrl">

    名: <input type="text" ng-model="firstName"><br>
    姓: <input type="text" ng-model="lastName"><br>
    <br>
    姓名: {{fullName()}}

    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('personCtrl', function($scope) {
        $scope.firstName = "John";
        $scope.lastName = "Doe";
        $scope.fullName = function() {
            return $scope.firstName + " " + $scope.lastName;
        }
    });
    </script>

    </body>
    </html>

     


    外部文件中的控制器

    在大型的应用程序中,通常是把控制器存储在外部文件中。

    只需要把 <script> 标签中的代码复制到名为personController.js的外部文件中即可:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="personCtrl">

    名: <input type="text" ng-model="firstName"><br>
    姓: <input type="text" ng-model="lastName"><br>
    <br>
    姓名: {{firstName + " " + lastName}}

    </div>

    <script src="personController.js"></script>

    </body>
    </html>

     


    其他实例

    以下实例创建一个新的控制器文件:

    angular.module('myApp', []).controller('namesCtrl', function($scope) {
        $scope.names = [
            {name:'Jani',country:'Norway'},
            {name:'Hege',country:'Sweden'},
            {name:'Kai',country:'Denmark'}
        ];
    });

    保存文件为namesController.js:

    然后,在应用中使用控制器文件:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="namesCtrl"> 

    <ul>
      <li ng-repeat="x in names">
        {{ x.name + ', ' + x.country }}
      </li>
    </ul>

    </div>

    <script src="namesController.js"></script>

    </body>
    </html>

     

     

    AngularJS 过滤器


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


    AngularJS 过滤器

    AngularJS 过滤器可用于转换数据:

    过滤器 描述
    currency 格式化数字为货币格式。
    filter 从数组项中选择一个子集。
    lowercase 格式化字符串为小写。
    orderBy 根据某个表达式排列数组。
    uppercase 格式化字符串为大写。

    表达式中添加过滤器

    过滤器可以通过一个管道字符(|)和一个过滤器添加到表达式中。.

    (下面的两个实例,我们将使用前面章节中提到的 person 控制器)

    uppercase 过滤器将字符串格式化为大写:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="http://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="personCtrl">

    <p>姓名为 {{ lastName | uppercase }}</p>

    </div>

    <script src="http://www.runoob.com/try/demo_source/personController.js"></script>

    </body>
    </html>

     

    lowercase 过滤器将字符串格式化为小写:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="http://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="personCtrl">

    <p>姓名为 {{ lastName | lowercase }}</p>

    </div>

    <script src="http://www.runoob.com/try/demo_source/personController.js"></script>

    </body>
    </html>

     


    currency 过滤器

    currency 过滤器将数字格式化为货币格式:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="costCtrl">

    数量: <input type="number" ng-model="quantity">
    价格: <input type="number" ng-model="price">

    <p>总价 = {{ (quantity * price) | currency }}</p>

    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('costCtrl', function($scope) {
        $scope.quantity = 1;
        $scope.price = 9.99;
    });
    </script>

    </body>
    </html>

     


    向指令添加过滤器

    过滤器可以通过一个管道字符(|)和一个过滤器添加到指令中。

    orderBy 过滤器根据表达式排列数组:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="namesCtrl">

    <p>循环对象:</p>
    <ul>
      <li ng-repeat="x in names | orderBy:'country'">
        {{ x.name + ', ' + x.country }}
      </li>
    </ul>

    </div>

    <script src="//www.runoob.com/try/demo_source/namesController.js"></script>

    </body>
    </html>

     


    过滤输入

    输入过滤器可以通过一个管道字符(|)和一个过滤器添加到指令中,该过滤器后跟一个冒号和一个模型名称。

    filter 过滤器从数组中选择一个子集:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="namesCtrl">

    <p>输入过滤:</p>

    <p><input type="text" ng-model="test"></p>

    <ul>
      <li ng-repeat="x in names | filter:test | orderBy:'country'">
        {{ (x.name | uppercase) + ', ' + x.country }}
      </li>
    </ul>

    </div>

    <script src="http://www.runoob.com/try/demo_source/namesController.js"></script>

    </body>
    </html>

     


    自定义过滤器

    以下实例自定义一个过滤器 reverse,将字符串反转:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>

    <body>

    <div ng-app="myApp" ng-controller="myCtrl">


    姓名: {{ msg | reverse }}

    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function($scope) {
        $scope.msg = "Runoob";
    });
    app.filter('reverse', function() { //可以注入依赖
        return function(text) {
            return text.split("").reverse().join("");
        }
    });
    </script>

    </body>
    </html>

     

    AngularJS 服务(Service)

    AngularJS 中你可以创建自己的服务,或使用内建服务。


    什么是服务?

    在 AngularJS 中,服务是一个函数或对象,可在你的 AngularJS 应用中使用。

    AngularJS 内建了30 多个服务。

    有个 $location 服务,它可以返回当前页面的 URL 地址。

    实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="myCtrl">
    <p> 当前页面的url:</p>
    <h3>{{myUrl}}</h3>
    </div>

    <p>该实例使用了内建的 $location 服务获取当前页面的 URL。</p>

    <script>
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function($scope, $location) {
        $scope.myUrl = $location.absUrl();
    });
    </script>

    </body>
    </html>

     

    注意 $location 服务是作为一个参数传递到 controller 中。如果要使用它,需要在 controller 中定义。


    为什么使用服务?

    在很多服务中,比如 $location 服务,它可以使用 DOM 中存在的对象,类似 window.location 对象,但 window.location 对象在 AngularJS 应用中有一定的局限性。

    AngularJS 会一直监控应用,处理事件变化, AngularJS 使用 $location 服务比使用 window.location 对象更好。

    $location vs window.location

      window.location $location.service
    目的 允许对当前浏览器位置进行读写操作 允许对当前浏览器位置进行读写操作
    API 暴露一个能被读写的对象 暴露jquery风格的读写器
    是否在AngularJS应用生命周期中和应用整合 可获取到应用生命周期内的每一个阶段,并且和$watch整合
    是否和HTML5 API的无缝整合 是(对低级浏览器优雅降级)
    和应用的上下文是否相关 否,window.location.path返回"/docroot/actual/path" 是,$location.path()返回"/actual/path"

    $http 服务

    $http 是 AngularJS 应用中最常用的服务。 服务向服务器发送请求,应用响应服务器传送过来的数据。

    实例

    使用 $http 服务向服务器请求数据:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="myCtrl"> 

    <p>欢迎信息:</p>

    <h1>{{myWelcome}}</h1>

    </div>

    <p> $http 服务向服务器请求信息,返回的值放入变量 "myWelcome" 中。</p>

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

    </body>
    </html>

     

    以上是一个非常简单的 $http 服务实例。


    $timeout 服务

    AngularJS $timeout 服务对应了 JS window.setTimeout 函数。

    实例

    两秒后显示信息:

    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="myCtrl"> 

    <p>两秒后显示信息:</p>

    <h1>{{myHeader}}</h1>

    </div>

    <p>$timeout 访问在规定的毫秒数后执行指定函数。</p>

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

    </body>
    </html>

     


    $interval 服务

    AngularJS $interval 服务对应了 JS window.setInterval 函数。

    实例

    每一秒显示信息:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="myCtrl"> 

    <p>现在时间是:</p>

    <h1>{{theTime}}</h1>

    </div>

    <p>$interval 访问在指定的周期(以毫秒计)来调用函数或计算表达式。</p>

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

    </body>
    </html>

     


    创建自定义服务

    你可以创建自定义服务,链接到你的模块中:

    创建名为hexafy 的服务:

    app.service('hexafy', function() {
        this.myFunc = function (x) {
            return x.toString(16);
        }
    });

    要使用自定义服务,需要在定义控制器的时候独立添加,设置依赖关系:

    实例

    使用自定义的的服务 hexafy 将一个数字转换为16进制数:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>
    <div ng-app="myApp" ng-controller="myCtrl">

    <p>255 的16进制是:</p>

    <h1>{{hex}}</h1>

    </div>

    <p>自定义服务,用于转换16进制数:</p>

    <script>
    var app = angular.module('myApp', []);

    app.service('hexafy', function() {
        this.myFunc = function (x) {
            return x.toString(16);
        }
    });
    app.controller('myCtrl', function($scope, hexafy) {
      $scope.hex = hexafy.myFunc(255);
    });
    </script>

    </body>
    </html>

     


    过滤器中,使用自定义服务

    当你创建了自定义服务,并连接到你的应用上后,你可以在控制器,指令,过滤器或其他服务中使用它。

    在过滤器 myFormat 中使用服务 hexafy:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp">
    在过滤器中使用服务:

    <h1>{{255 | myFormat}}</h1>

    </div>

    <script>
    var app = angular.module('myApp', []);
    app.service('hexafy', function() {
        this.myFunc = function (x) {
            return x.toString(16);
        }
    });
    app.filter('myFormat',['hexafy', function(hexafy) {
        return function(x) {
            return hexafy.myFunc(x);
        };
    }]);

    </script>

    </body>
    </html>

     

    在对象数组中获取值时你可以使用过滤器:

    创建服务 hexafy:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="myCtrl">
    <p>在获取数组 [255, 251, 200] 值时使用过滤器:</p>

    <ul>
      <li ng-repeat="x in counts">{{x | myFormat}}</li>
    </ul>

    <p>过滤器使用服务将10进制转换为16进制。</p>
    </div>

    <script>
    var app = angular.module('myApp', []);
    app.service('hexafy', function() {
        this.myFunc = function (x) {
            return x.toString(16);
        }
    });
    app.filter('myFormat',['hexafy', function(hexafy) {
        return function(x) {
            return hexafy.myFunc(x);
        };
    }]);
    app.controller('myCtrl', function($scope) {
        $scope.counts = [255, 251, 200];
    });
    </script>

    </body>
    </html>

     

    AngularJS XMLHttpRequest


    $http 是 AngularJS 中的一个核心服务,用于读取远程服务器的数据。

    使用格式:

    // 简单的 GET 请求,可以改为 POST
    $http({
        method: 'GET',
        url: '/someUrl'
    }).then(function successCallback(response) {
            // 请求成功执行代码
        }, function errorCallback(response) {
            // 请求失败执行代码
    });

    简写方法

    POST 与 GET 简写方法格式:

    $http.get('/someUrl', config).then(successCallback, errorCallback);
    $http.post('/someUrl', data, config).then(successCallback, errorCallback);

    此外还有以下简写方法:

    • $http.get
    • $http.head
    • $http.post
    • $http.put
    • $http.delete
    • $http.jsonp
    • $http.patch

     


    读取 JSON 文件

    以下是存储在web服务器上的 JSON 文件:

    http://www.runoob.com/try/angularjs/data/sites.php

    { "sites": [

                         { "Name": "angularjs教程", "Url": "www.runoob.com", "Country": "CN" },

                         { "Name": "Google", "Url": "www.google.com", "Country": "USA" },

                         { "Name": "Facebook", "Url": "www.facebook.com", "Country": "USA" },

                        { "Name": "微博", "Url": "www.weibo.com", "Country": "CN" }

                  ]

    }


    AngularJS $http

    AngularJS $http 是一个用于读取web服务器上数据的服务。

    $http.get(url) 是用于读取服务器数据的函数。

    废弃声明 (v1.5)

    v1.5 中$http 的 success 和 error 方法已废弃。使用 then 方法替代。

    通用方法实例

    AngularJS1.5 以上版本 - 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.6.3/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="siteCtrl"> 

    <ul>
      <li ng-repeat="x in names">
        {{ x.Name + ', ' + x.Country }}
      </li>
    </ul>

    </div>

    <script>
    var app = angular.module('myApp', []);
        
    app.controller('siteCtrl', function($scope, $http) {
        $http({
            method: 'GET',
            url: 'http://www.runoob.com/try/angularjs/data/sites.php'
        }).then(function successCallback(response) {
                $scope.names = response.data.sites;
            }, function errorCallback(response) {
                // 请求失败执行代码
        });
      
    });
    </script>

    </body>
    </html>

     

    简写方法实例

    AngularJS1.5 以上版本 - 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.6.3/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="siteCtrl"> 

    <ul>
      <li ng-repeat="x in names">
        {{ x.Name + ', ' + x.Country }}
      </li>
    </ul>

    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('siteCtrl', function($scope, $http) {
      $http.get("http://www.runoob.com/try/angularjs/data/sites.php")
      .then(function (response) {$scope.names = response.data.sites;});
    });
    </script>

    </body>
    </html>

     

    AngularJS1.5 以下版本 - 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="siteCtrl"> 

    <ul>
      <li ng-repeat="x in names">
        {{ x.Name + ', ' + x.Country }}
      </li>
    </ul>

    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('siteCtrl', function($scope, $http) {
      $http.get("http://www.runoob.com/try/angularjs/data/sites.php")
      .success(function (response) {$scope.names = response.sites;});
    });
    </script>

    </body>
    </html>

     

    应用解析:

    注意:以上代码的 get 请求是本站的服务器,你不能直接拷贝到你本地运行,会存在跨域问题,解决办法就是将 Customers_JSON.php 的数据拷贝到你自己的服务器上

    AngularJS 应用通过 ng-app 定义。应用在 <div> 中执行。

    ng-controller 指令设置了 controller 对象 名。

    函数 customersController 是一个标准的 JavaScript 对象构造器

    控制器对象有一个属性: $scope.names

    $http.get() 从web服务器上读取静态 JSON 数据

    服务器数据文件为:http://www.runoob.com/try/angularjs/data/sites.php。

    当从服务端载入 JSON 数据时,$scope.names 变为一个数组。

     

    以上代码也可以用于读取数据库数据。

     

    AngularJS Select(选择框)

    AngularJS 可以使用数组或对象创建一个下拉列表选项。


    使用 ng-options 创建选择框

    在 AngularJS 中我们可以使用 ng-option 指令来创建一个下拉列表,列表项通过对象和数组循环输出,如下实例:

    实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="myCtrl">

    <select ng-init="selectedName = names[0]" ng-model="selectedName" ng-options="x for x in names">
    </select>

    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function($scope) {
        $scope.names = ["Google", "Runoob", "Taobao"];
    });
    </script>

    <p>该实例演示了 ng-options 指令的使用。</p>

    </body>
    </html>

     

    ng-init 设置默认选中值。


    ng-options 与 ng-repeat

    我们也可以使用ng-repeat 指令来创建下拉列表:

    实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="myCtrl">

    <select>
    <option ng-repeat="x in names">{{x}}</option>
    </select>

    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function($scope) {
        $scope.names = ["Google", "Runoob", "Taobao"];
    });
    </script>

    <p>该实例演示了使用 ng-repeat 指令来创建下拉列表。</p>

    </body>
    </html>

     

    ng-repeat 指令是通过数组来循环 HTML 代码来创建下拉列表,但 ng-options 指令更适合创建下拉列表,它有以下优势:

    使用 ng-options 的选项是一个对象, ng-repeat 是一个字符串。


    应该用哪个更好?

    假设我们使用以下对象:

    $scope.sites = [
        {site : "Google", url : "http://www.google.com"},
        {site : "Runoob", url : "http://www.runoob.com"},
        {site : "Taobao", url : "http://www.taobao.com"}
    ];

    ng-repeat 有局限性,选择的值是一个字符串:

    实例

    使用 ng-repeat:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="myCtrl">

    <p>选择网站:</p>

    <select ng-model="selectedSite">
    <option ng-repeat="x in sites" value="{{x.url}}">{{x.site}}</option>
    </select>

    <h1>你选择的是: {{selectedSite}}</h1>

    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function($scope) {
       $scope.sites = [
            {site : "Google", url : "http://www.google.com"},
            {site : "Runoob", url : "http://www.runoob.com"},
            {site : "Taobao", url : "http://www.taobao.com"}
        ];
    });
    </script>

    <p>该实例演示了使用 ng-repeat 指令来创建下拉列表,选中的值是一个字符串。</p>
    </body>
    </html>

     

    使用 ng-options 指令,选择的值是一个对象:

    实例

    使用 ng-options:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="myCtrl">

    <p>选择网站:</p>

    <select ng-model="selectedSite" ng-options="x.site for x in sites">
    </select>

    <h1>你选择的是: {{selectedSite.site}}</h1>
    <p>网址为: {{selectedSite.url}}</p>

    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function($scope) {
       $scope.sites = [
            {site : "Google", url : "http://www.google.com"},
            {site : "Runoob", url : "http://www.runoob.com"},
            {site : "Taobao", url : "http://www.taobao.com"}
        ];
    });
    </script>

    <p>该实例演示了使用 ng-options  指令来创建下拉列表,选中的值是一个对象。</p>
    </body>
    </html>

     

    当选择值是一个对象时,我们就可以获取更多信息,应用也更灵活。


    数据源为对象

    前面实例我们使用了数组作为数据源,以下我们将数据对象作为数据源。

    $scope.sites = {
        site01 : "Google",
        site02 : "Runoob",
        site03 : "Taobao"
    };

    ng-options 使用对象有很大的不同,如下所示:

    实例

    使用对象作为数据源, x 为键(key), y 为值(value):

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="myCtrl">

    <p>选择的网站是:</p>

    <select ng-model="selectedSite" ng-options="x for (x, y) in sites">
    </select>

    <h1>你选择的值是: {{selectedSite}}</h1>

    </div>

    <p>该实例演示了使用对象作为创建下拉列表。</p>

    <script>
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function($scope) {
        $scope.sites = {
            site01 : "Google",
            site02 : "Runoob",
            site03 : "Taobao"
        };
    });
    </script>

    </body>
    </html>

     

    你选择的值为在 key-value 对中的 value

    value 在 key-value 对中也可以是个对象:

    实例

    选择的值在 key-value 对的 value 中, 这时它是一个对象:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="myCtrl">

    <p>选择一辆车:</p>

    <select ng-model="selectedCar" ng-options="x for (x, y) in cars">
    </select>

    <h1>你选择的是: {{selectedCar.brand}}</h1>
    <h2>模型: {{selectedCar.model}}</h2>
    <h3>颜色: {{selectedCar.color}}</h3>

    <p>注意选中的值是一个对象。</p>
    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function($scope) {
        $scope.cars = {
            car01 : {brand : "Ford", model : "Mustang", color : "red"},
            car02 : {brand : "Fiat", model : "500", color : "white"},
            car03 : {brand : "Volvo", model : "XC90", color : "black"}
        }
    });
    </script>

    </body>
    </html>

     

    在下拉菜单也可以不使用 key-value 对中的 key , 直接使用对象的属性:

    实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="myCtrl">

    <p>选择一辆车:</p>

    <select ng-model="selectedCar" ng-options="y.brand for (x, y) in cars"></select>
    <p>你选择的是: {{selectedCar.brand}}</p>
    <p>型号为: {{selectedCar.model}}</p>
    <p>颜色为: {{selectedCar.color}}</p>

    <p>下拉列表中的选项也可以是对象的属性。</p>

    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function($scope) {
        $scope.cars = {
            car01 : {brand : "Ford", model : "Mustang", color : "red"},
            car02 : {brand : "Fiat", model : "500", color : "white"},
            car03 : {brand : "Volvo", model : "XC90", color : "black"}
        }
    });
    </script>

    </body>
    </html>

     

    AngularJS 表格


    ng-repeat 指令可以完美的显示表格。


    在表格中显示数据

    使用 angular 显示表格是非常简单的:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.6.3/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="customersCtrl"> 

    <table>
      <tr ng-repeat="x in names">
        <td>{{ x.Name }}</td>
        <td>{{ x.Country }}</td>
      </tr>
    </table>

    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('customersCtrl', function($scope, $http) {
        $http.get("/try/angularjs/data/Customers_JSON.php")
        .then(function (result) {
            $scope.names = result.data.records;
        });
    });
    </script>

    </body>
    </html>

     

    废弃声明 (v1.5)

    v1.5 中$http 的 success 和 error 方法已废弃。使用 then 方法替代。

    如果你使用的是 v1.5 以下版本,可以使用以下代码:

    var app = angular.module('myApp', []);
    app.controller('customersCtrl', function($scope, $http) {
        $http.get("/try/angularjs/data/Customers_JSON.php")
        .success(function (response) {$scope.names = response.records;});
    });

    Customers_JSON.php 文件代码:

    <?php

    echo <<<EOT

    {

    "records":[

                    {"Name":"Alfreds Futterkiste","City":"Berlin","Country":"Germany"},

                    {"Name":"Ana Trujillo Emparedados y helados","City":"México D.F.","Country":"Mexico"},

                    {"Name":"Antonio Moreno Taquería","City":"México D.F.","Country":"Mexico"},

                    {"Name":"Around the Horn","City":"London","Country":"UK"},

                    {"Name":"B's Beverages","City":"London","Country":"UK"},

                    {"Name":"Berglunds snabbköp","City":"Luleå","Country":"Sweden"},

                    {"Name":"Blauer See Delikatessen","City":"Mannheim","Country":"Germany"},

                    {"Name":"Blondel père et fils","City":"Strasbourg","Country":"France"},

                    {"Name":"Bólido Comidas preparadas","City":"Madrid","Country":"Spain"},

                    {"Name":"Bon app'","City":"Marseille","Country":"France"},

                   {"Name":"Bottom-Dollar Marketse","City":"Tsawassen","Country":"Canada"},

                   {"Name":"Cactus Comidas para llevar","City":"Buenos Aires","Country":"Argentina"},

                   {"Name":"Centro comercial Moctezuma","City":"México D.F.","Country":"Mexico"},

                   {"Name":"Chop-suey Chinese","City":"Bern","Country":"Switzerland"},

                   {"Name":"Comércio Mineiro","City":"São Paulo","Country":"Brazil"} 

                ] 

    EOT;

    ?>


    使用 CSS 样式

    为了让页面更加美观,我们可以在页面中使用CSS:

    CSS 样式

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.6.3/angular.min.js"></script>
    <style>
    table, th , td  {
      border: 1px solid grey;
      border-collapse: collapse;
      padding: 5px;
    }
    table tr:nth-child(odd)    {
      background-color: #f1f1f1;
    }
    table tr:nth-child(even) {
      background-color: #ffffff;
    }
    </style>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="customersCtrl"> 

    <table>
      <tr ng-repeat="x in names">
        <td>{{ x.Name }}</td>
        <td>{{ x.Country }}</td>
      </tr>
    </table>

    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('customersCtrl', function($scope, $http) {
        $http.get("/try/angularjs/data/Customers_JSON.php")
        .then(function (result) {
            $scope.names = result.data.records;
        });
    });
    </script>

    </body>
    </html>

     


    使用 orderBy 过滤器

    排序显示,可以使用 orderBy 过滤器: 

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.6.3/angular.min.js"></script>
    <style>
    table, th , td  {
      border: 1px solid grey;
      border-collapse: collapse;
      padding: 5px;
    }
    table tr:nth-child(odd)    {
      background-color: #f1f1f1;
    }
    table tr:nth-child(even) {
      background-color: #ffffff;
    }
    </style>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="customersCtrl"> 

    <table>
      <tr ng-repeat="x in names | orderBy : 'Country'">
        <td>{{ x.Name }}</td>
        <td>{{ x.Country }}</td>
      </tr>
    </table>

    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('customersCtrl', function($scope, $http) {
        $http.get("/try/angularjs/data/Customers_JSON.php")
        .then(function (result) {
            $scope.names = result.data.records;
        });
    });
    </script>

    </body>
    </html>

     


    使用 uppercase 过滤器

    使用 uppercase 过滤器转换为大写: 

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.6.3/angular.min.js"></script>
    <style>
    table, th , td  {
      border: 1px solid grey;
      border-collapse: collapse;
      padding: 5px;
    }
    table tr:nth-child(odd)    {
      background-color: #f1f1f1;
    }
    table tr:nth-child(even) {
      background-color: #ffffff;
    }
    </style>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="customersCtrl"> 

    <table>
      <tr ng-repeat="x in names">
        <td>{{ x.Name }}</td>
        <td>{{ x.Country | uppercase }}</td>
      </tr>
    </table>

    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('customersCtrl', function($scope, $http) {
        $http.get("/try/angularjs/data/Customers_JSON.php")
        .then(function (result) {
            $scope.names = result.data.records;
        });
    });
    </script>

    </body>
    </html>

     


    显示序号 ($index)

    表格显示序号可以在 <td> 中添加 $index

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.6.3/angular.min.js"></script>
    <style>
    table, th , td  {
      border: 1px solid grey;
      border-collapse: collapse;
      padding: 5px;
    }
    table tr:nth-child(odd)    {
      background-color: #f1f1f1;
    }
    table tr:nth-child(even) {
      background-color: #ffffff;
    }
    </style>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="customersCtrl"> 

    <table>
      <tr ng-repeat="x in names">
        <td>{{ $index + 1 }}</td>
        <td>{{ x.Name }}</td>
        <td>{{ x.Country }}</td>
      </tr>
    </table>

    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('customersCtrl', function($scope, $http) {
        $http.get("/try/angularjs/data/Customers_JSON.php")
        .then(function (result) {
            $scope.names = result.data.records;
        });
    });
    </script>

    </body>
    </html>

     


    使用 $even 和 $odd

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.6.3/angular.min.js"></script>
    <style>
    table, td  {
      border: 1px solid grey;
      border-collapse: collapse;
      padding: 5px;
    }
    </style>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="customersCtrl"> 

    <table>
      <tr ng-repeat="x in names">
        <td ng-if="$odd" style="background-color:#f1f1f1">
        {{ x.Name }}</td>
        <td ng-if="$even">
        {{ x.Name }}</td>
        <td ng-if="$odd" style="background-color:#f1f1f1">
        {{ x.Country }}</td>
        <td ng-if="$even">
        {{ x.Country }}</td>
      </tr>
    </table>

    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('customersCtrl', function($scope, $http) {
        $http.get("/try/angularjs/data/Customers_JSON.php")
        .then(function (result) {
            $scope.names = result.data.records;
        });
    });
    </script>

    </body>
    </html>

     

    AngularJS SQL


    在前面章节中的代码也可以用于读取数据库中的数据。


    使用 PHP 从 MySQL 中获取数据

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    <style>
    table, th , td  {
      border: 1px solid grey;
      border-collapse: collapse;
      padding: 5px;
    }
    table tr:nth-child(odd) {
      background-color: #f1f1f1;
    }
    table tr:nth-child(even) {
      background-color: #ffffff;
    }
    </style>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="customersCtrl">
     
    <table>
      <tr ng-repeat="x in names">
        <td>{{ x.Name }}</td>
        <td>{{ x.Country }}</td>
      </tr>
    </table>
     
    </div>
     
    <script>
    var app = angular.module('myApp', []);
    app.controller('customersCtrl', function($scope, $http) {
       $http.get("/try/angularjs/data/Customers_MySQL.php")
       .success(function (response) {$scope.names = response.records;});
    });
    </script>

    </body>
    </html>

     


    ASP.NET 中执行 SQL 获取数据

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    <style>
    table, th , td  {
      border: 1px solid grey;
      border-collapse: collapse;
      padding: 5px;
    }
    table tr:nth-child(odd) {
      background-color: #f1f1f1;
    }
    table tr:nth-child(even) {
      background-color: #ffffff;
    }
    </style>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="customersCtrl"> 

    <table>
    <tr ng-repeat="x in names">
        <td>{{ x.Name }}</td>
        <td>{{ x.Country }}</td>
    </tr>
    </table>

    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('customersCtrl', function($scope, $http) {
       $http.get("http://www.runoob.com/try/angularjs/data/Customers_SQL.aspx")
       .success(function (response) {$scope.names = response.records;});
    });
    </script>

    </body>
    </html>

     


    服务端代码

    以下列出了几种服务端代码类型:

    1. 使用 PHP 和 MySQL。返回 JSON。
    2. 使用 PHP 和 MS Access。返回 JSON。
    3. 使用 ASP.NET, VB, 及 MS Access。 返回 JSON。
    4. 使用 ASP.NET, Razor, 及 SQL Lite。 返回 JSON。

    跨域 HTTP 请求

    如果你需要从不同的服务器(不同域名)上获取数据就需要使用跨域 HTTP 请求。

    跨域请求在网页上非常常见。很多网页从不同服务器上载入 CSS, 图片,Js脚本等。

    在现代浏览器中,为了数据的安全,所有请求被严格限制在同一域名下,如果需要调用不同站点的数据,需要通过跨域来解决。

    以下的 PHP 代码运行使用的网站进行跨域访问。

    header("Access-Control-Allow-Origin: *");

     


    1. PHP 和 MySql 代码实例

    <?php
    header("Access-Control-Allow-Origin: *");
    header("Content-Type: application/json; charset=UTF-8");

    $conn = new mysqli("myServer", "myUser", "myPassword", "Northwind");

    $result = $conn->query("SELECT CompanyName, City, Country FROM Customers");

    $outp = "";
    while($rs = $result->fetch_array(MYSQLI_ASSOC)) {
        if ($outp != "") {$outp .= ",";}
        $outp .= '{"Name":"'  . $rs["CompanyName"] . '",';
        $outp .= '"City":"'   . $rs["City"]        . '",';
        $outp .= '"Country":"'. $rs["Country"]     . '"}'; 
    }
    $outp ='{"records":['.$outp.']}';
    $conn->close();

    echo($outp);
    ?>


    2. PHP 和 MS Access 代码实例

    <?php
    header("Access-Control-Allow-Origin: *");
    header("Content-Type: application/json; charset=ISO-8859-1");

    $conn = new COM("ADODB.Connection");
    $conn->open("PROVIDER=Microsoft.Jet.OLEDB.4.0;Data Source=Northwind.mdb");

    $rs = $conn->execute("SELECT CompanyName, City, Country FROM Customers");

    $outp = "";
    while (!$rs->EOF) {
        if ($outp != "") {$outp .= ",";}
        $outp .= '{"Name":"'  . $rs["CompanyName"] . '",';
        $outp .= '"City":"'   . $rs["City"]        . '",';
        $outp .= '"Country":"'. $rs["Country"]     . '"}'; 
        $rs->MoveNext();
    }
    $outp ='{"records":['.$outp.']}';

    $conn->close();

    echo ($outp);
    ?>


    3. ASP.NET, VB 和 MS Access 代码实例

    <%@ Import Namespace="System.IO"%>
    <%@ Import Namespace="System.Data"%>
    <%@ Import Namespace="System.Data.OleDb"%>
    <%
    Response.AppendHeader("Access-Control-Allow-Origin", "*")
    Response.AppendHeader("Content-type", "application/json")
    Dim conn As OleDbConnection
    Dim objAdapter As OleDbDataAdapter
    Dim objTable As DataTable
    Dim objRow As DataRow
    Dim objDataSet As New DataSet()
    Dim outp
    Dim c
    conn = New OledbConnection("Provider=Microsoft.Jet.OLEDB.4.0;data source=Northwind.mdb")
    objAdapter = New OledbDataAdapter("SELECT CompanyName, City, Country FROM Customers", conn)
    objAdapter.Fill(objDataSet, "myTable")
    objTable=objDataSet.Tables("myTable")

    outp = ""
    c = chr(34)
    for each x in objTable.Rows
    if outp <> "" then outp = outp & ","
    outp = outp & "{" & c & "Name"    & c & ":" & c & x("CompanyName") & c & ","
    outp = outp &       c & "City"    & c & ":" & c & x("City")        & c & "," 
    outp = outp &       c & "Country" & c & ":" & c & x("Country")     & c & "}"
    next

    outp ="{" & c & "records" & c & ":[" & outp & "]}"
    response.write(outp)
    conn.close
    %>


    4. ASP.NET, VB Razor 和 SQL Lite 代码实例

    @{
    Response.AppendHeader("Access-Control-Allow-Origin", "*")
    Response.AppendHeader("Content-type", "application/json")
    var db = Database.Open("Northwind");
    var query = db.Query("SELECT CompanyName, City, Country FROM Customers");
    var outp =""
    var c = chr(34)
    }
    @foreach(var row in query)
    {
    if outp <> "" then outp = outp + ","
    outp = outp + "{" + c + "Name"    + c + ":" + c + @row.CompanyName + c + ","
    outp = outp +       c + "City"    + c + ":" + c + @row.City        + c + ","
    outp = outp +       c + "Country" + c + ":" + c + @row.Country     + c + "}"
    }
    outp ="{" + c + "records" + c + ":[" + outp + "]}"
    @outp

     

    AngularJS HTML DOM


    AngularJS 为 HTML DOM 元素的属性提供了绑定应用数据的指令。


    ng-disabled 指令

    ng-disabled 指令直接绑定应用程序数据到 HTML 的 disabled 属性。

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="" ng-init="mySwitch=true">
    <p>
    <button ng-disabled="mySwitch">点我!</button>
    </p>
    <p>
    <input type="checkbox" ng-model="mySwitch"/>按钮
    </p>
    <p>
    {{ mySwitch }}
    </p>
    </div> 

    </body>
    </html>

     

    实例讲解:

    ng-disabled 指令绑定应用程序数据 "mySwitch" 到 HTML 的 disabled 属性。

    ng-model 指令绑定 "mySwitch" 到 HTML input checkbox 元素的内容(value)。

    如果 mySwitch 为true, 按钮将不可用: 

    <p>
    <button disabled>点我!</button>
    </p>

    如果 mySwitch 为false, 按钮则可用: 

    <p>
    <button>点我!</button>
    </p>


    ng-show 指令

    ng-show 指令隐藏或显示一个 HTML 元素。

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="">

    <p ng-show="true">我是可见的。</p>

    <p ng-show="false">我是不可见的。</p>

    </div> 

    </body>
    </html>

     

    ng-show 指令根据 value 的值来显示(隐藏)HTML 元素。

    你可以使用表达式来计算布尔值( true 或 false):

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="" ng-init="hour=13">

    <p ng-show="hour > 12">我是可见的。</p>

    </div>

    </body>
    </html>


    ng-hide 指令

    ng-hide 指令用于隐藏或显示 HTML 元素。

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="">

    <p ng-hide="true">我是不可见的。</p>

    <p ng-hide="false">我是可见的。</p>

    </div> 

    </body>
    </html>

     

    AngularJS 事件


    AngularJS 有自己的 HTML 事件指令。


    ng-click 指令

    ng-click 指令定义了 AngularJS 点击事件。

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="myCtrl">

    <button ng-click="count = count + 1">点我!</button>

    <p>{{ count }}</p>

    </div>
    <script>
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function($scope) {
        $scope.count = 0;
    });
    </script>

    </body>
    </html>

     


    隐藏 HTML 元素

    ng-hide 指令用于设置应用部分是否可见。

    ng-hide="true" 设置 HTML 元素不可见。

    ng-hide="false" 设置 HTML 元素可见。

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="personCtrl">

    <button ng-click="toggle()">隐藏/显示</button>

    <p ng-hide="myVar">
    名: <input type=text ng-model="firstName"><br>
    姓: <input type=text ng-model="lastName"><br><br>
    姓名: {{firstName + " " + lastName}}
    </p>

    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('personCtrl', function($scope) {
        $scope.firstName = "John";
        $scope.lastName = "Doe";
        $scope.myVar = false;
        $scope.toggle = function() {
            $scope.myVar = !$scope.myVar;
        }
    });
    </script>

    </body>
    </html>

     

    应用解析:

    第一部分 personController与控制器章节类似。

    应用有一个默认属性: $scope.myVar = false;

    ng-hide 指令设置 <p>元素及两个输入域是否可见, 根据 myVar 的值 (true 或 false) 来设置是否可见。

    toggle() 函数用于切换 myVar 变量的值(true 和 false)。

    ng-hide="true" 让元素 不可见


    显示 HTML 元素

    ng-show 指令可用于设置应用中的一部分是否可见 。

    ng-show="false" 可以设置 HTML 元素 不可见

    ng-show="true" 可以以设置 HTML 元素可见。

    以下实例使用了 ng-show 指令:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="personCtrl">

    <button ng-click="toggle()">隐藏/显示</button>

    <p ng-show="myVar">
    名: <input type=text ng-model="person.firstName"><br>
    姓: <input type=text ng-model="person.lastName"><br><br>
    姓名: {{person.firstName + " " + person.lastName}}
    </p>

    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('personCtrl', function($scope) {
        $scope.person = {
            firstName: "John",
            lastName: "Doe"
        };
        $scope.myVar = true;
        $scope.toggle = function() {
            $scope.myVar = !$scope.myVar;
        };
    });
    </script>

    </body>
    </html>

     

    AngularJS 模块


    模块定义了一个应用程序。

    模块是应用程序中不同部分的容器。

    模块是应用控制器的容器。

    控制器通常属于一个模块。


    创建模块

    你可以通过 AngularJS 的 angular.module 函数来创建模块:

    <div ng-app="myApp">...</div>

    <script>


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

    </script>

    "myApp" 参数对应执行应用的 HTML 元素。

    现在你可以在 AngularJS 应用中添加控制器,指令,过滤器等。


    添加控制器

    你可以使用 ng-controller 指令来添加应用的控制器:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body>

    <div ng-app="myApp" ng-controller="myCtrl">
    {{ firstName + " " + lastName }}
    </div>

    <script>
    var app = angular.module("myApp", []);
    app.controller("myCtrl", function($scope) {
        $scope.firstName = "John";
        $scope.lastName = "Doe";
    });
    </script>

    </body>
    </html>

     

     


    添加指令

    AngularJS 提供了很多内置的指令,你可以使用它们来为你的应用添加功能。

    此外,你可以使用模块来为你应用添加自己的指令:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body>

    <div ng-app="myApp" runoob-directive></div>

    <script>

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

    app.directive("runoobDirective", function() {
        return {
            template : "我在指令构造器中创建!"
        };
    });
    </script>

    </body>
    </html>

     

     


    模块和控制器包含在 JS 文件中

    通常 AngularJS 应用程序将模块和控制器包含在 JavaScript 文件中。

    在以下实例中, "myApp.js" 包含了应用模块的定义程序, "myCtrl.js" 文件包含了控制器:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script> 
    </head>
    <body>

    <div ng-app="myApp" ng-controller="myCtrl">
    {{ firstName + " " + lastName }}
    </div>

    <script src="myApp.js"></script>
    <script src="myCtrl.js"></script>

    </body>
    </html>

     

     

    myApp.js

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

     

    在模块定义中 [] 参数用于定义模块的依赖关系。
    中括号[]表示该模块没有依赖,如果有依赖的话会在中括号写上依赖的模块名字。

     

    myCtrl.js

    app.controller("myCtrl", function($scope) {
        $scope.firstName = "John";
        $scope.lastName= "Doe";
    });


    函数会影响到全局命名空间

    JavaScript 中应避免使用全局函数。因为他们很容易被其他脚本文件覆盖。

    AngularJS 模块让所有函数的作用域在该模块下,避免了该问题。


    什么时候载入库?

    在我们的实例中,所有 AngularJS 库都在 HTML 文档的头部载入。

    对于 HTML 应用程序,通常建议把所有的脚本都放置在 <body> 元素的最底部。

    这会提高网页加载速度,因为 HTML 加载不受制于脚本加载。

    在我们的多个 AngularJS 实例中,您将看到 AngularJS 库是在文档的 <head> 区域被加载。

    在我们的实例中,AngularJS 在 <head> 元素中被加载,因为对 angular.module 的调用只能在库加载完成后才能进行。

    另一个解决方案是在 <body> 元素中加载 AngularJS 库,但是必须放置在您的 AngularJS 脚本前面:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="myCtrl">
    {{ firstName + " " + lastName }}
    </div>
    <script>
    var app = angular.module("myApp", []);
    app.controller("myCtrl", function($scope) {
        $scope.firstName = "John";
        $scope.lastName = "Doe";
    });
    </script>

    </body>
    </html>

     

    AngularJS 表单


    AngularJS 表单是输入控件的集合。


    HTML 控件

    以下 HTML input 元素被称为 HTML 控件:

    • input 元素
    • select 元素
    • button 元素
    • textarea 元素

    数据绑定

    Input 控件使用 ng-model 指令来实现数据绑定。

    <input type="text" ng-model="firstname">

    通过以上代码应用有了一个名为 firstname 的属性。

    它通过 ng-model 指令来绑定到你的应用。

    firstname 属性可以在 controller 中使用:

    实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="formCtrl">
      <form>
        First Name: <input type="text" ng-model="firstname">
      </form>
    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('formCtrl', function($scope) {
        $scope.firstname = "John";
    });
    </script>

    </body>
    </html>

     

    也可以在应用的其他地方使用:

    实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="">
      <form>
        First Name: <input type="text" ng-model="firstname">
      </form>
      <h1>你输入的内容为: {{firstname}}</h1>
    </div>

    <p>修改输出框的内容,显示信息也会跟着变化。</p>

    </body>
    </html>

     


    Checkbox(复选框)

    checkbox 的值为 true 或 false,可以使用 ng-model 指令绑定,它的值可以用于应用中:

    实例

    复选框选中后显示 h1 标签内容:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="">
      <form>
        选中复选框,显示标题:
        <input type="checkbox" ng-model="myVar">
      </form>
      <h1 ng-show="myVar">My Header</h1>
    </div>

    <p>标题使用了 ng-show 指令,复选框选中后显示 h1 标签内容。</p>


    </body>
    </html>

     


    单选框

    我们可以使用 ng-model 来绑定单选按钮到你的应用中。

    单选框使用同一个 ng-model ,可以有不同的值,但只有被选中的单选按钮的值会被使用。

    实例

    根据选中的单选按钮,显示信息:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body ng-app="">

    <form>
      选择一个选项:
      <input type="radio" ng-model="myVar" value="dogs">Dogs
      <input type="radio" ng-model="myVar" value="tuts">Tutorials
      <input type="radio" ng-model="myVar" value="cars">Cars
    </form>

    <div ng-switch="myVar">
      <div ng-switch-when="dogs">
         <h1>Dogs</h1>
         <p>Welcome to a world of dogs.</p>
      </div>
      <div ng-switch-when="tuts">
         <h1>Tutorials</h1>
         <p>Learn from examples.</p>
      </div>
      <div ng-switch-when="cars">
         <h1>Cars</h1>
         <p>Read about cars.</p>
      </div>
    </div>

    <p>ng-switch 指令根据单选按钮的选择结果显示或隐藏 HTML 区域。</p>

    </body>
    </html>

     

    myVar 的值可以是 dogs, tuts, 或 cars。


    下拉菜单

    使用 ng-model 指令可以将下拉菜单绑定到你的应用中。

    ng-model 属性的值为你在下拉菜单选中的选项:

    实例

    根据选中的下拉菜单选项,显示信息:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body ng-app="">

    <form>
      选择一个选项:
      <select ng-model="myVar">
        <option value="">
        <option value="dogs">Dogs
        <option value="tuts">Tutorials
        <option value="cars">Cars
      </select>
    </form>

    <div ng-switch="myVar">
      <div ng-switch-when="dogs">
         <h1>Dogs</h1>
         <p>Welcome to a world of dogs.</p>
      </div>
      <div ng-switch-when="tuts">
         <h1>Tutorials</h1>
         <p>Learn from examples.</p>
      </div>
      <div ng-switch-when="cars">
         <h1>Cars</h1>
         <p>Read about cars.</p>
      </div>
    </div>

    <p>ng-switch 指令根据下拉菜单的选择结果显示或隐藏 HTML 区域。</p>

    </body>
    </html>

     

    myVar 的值可以是 dogs, tuts, 或 cars。

    HTML 表单

    HTML 表单通常与 HTML 控件同时存在。


    AngularJS 表单实例

    First Name:

    Last Name:
     

    RESET

    form = {"firstName":"John","lastName":"Doe"}

    master = {"firstName":"John","lastName":"Doe"}


    应用程序代码

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="formCtrl">
      <form novalidate>
        First Name:<br>
        <input type="text" ng-model="user.firstName"><br>
        Last Name:<br>
        <input type="text" ng-model="user.lastName">
        <br><br>
        <button ng-click="reset()">RESET</button>
      </form>
      <p>form = {{user}}</p>
      <p>master = {{master}}</p>
    </div>
     
    <script>
    var app = angular.module('myApp', []);
    app.controller('formCtrl', function($scope) {
        $scope.master = {firstName: "John", lastName: "Doe"};
        $scope.reset = function() {
            $scope.user = angular.copy($scope.master);
        };
        $scope.reset();
    });
    </script>
        
    </body>
    </html>

    novalidate 属性是在 HTML5 中新增的。禁用了使用浏览器的默认验证。

     


    实例解析

    ng-app 指令定义了 AngularJS 应用。

    ng-controller 指令定义了应用控制器。

    ng-model 指令绑定了两个 input 元素到模型的 user 对象。

    formCtrl 函数设置了 master 对象的初始值,并定义了 reset() 方法。

    reset() 方法设置了 user 对象等于 master 对象。

    ng-click 指令调用了 reset() 方法,且在点击按钮时调用。

    novalidate 属性在应用中不是必须的,但是你需要在 AngularJS 表单中使用,用于重写标准的 HTML5 验证。

     

    AngularJS 输入验证


    AngularJS 表单和控件可以验证输入的数据。


    输入验证

    在前面的几个章节中,你已经学到关于 AngularJS 表单和控件的知识。

    AngularJS 表单和控件可以提供验证功能,并对用户输入的非法数据进行警告。

     

    客户端的验证不能确保用户输入数据的安全,所以服务端的数据验证也是必须的。


    应用代码

    <!DOCTYPE html>
    <html>
    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
    <body>

    <h2>Validation Example</h2>

    <form  ng-app="myApp"  ng-controller="validateCtrl"
    name="myForm" novalidate>

    <p>用户名:<br>
      <input type="text" name="user" ng-model="user" required>
      <span style="color:red" ng-show="myForm.user.$dirty && myForm.user.$invalid">
      <span ng-show="myForm.user.$error.required">用户名是必须的。</span>
      </span>
    </p>

    <p>邮箱:<br>
      <input type="email" name="email" ng-model="email" required>
      <span style="color:red" ng-show="myForm.email.$dirty && myForm.email.$invalid">
      <span ng-show="myForm.email.$error.required">邮箱是必须的。</span>
      <span ng-show="myForm.email.$error.email">非法的邮箱。</span>
      </span>
    </p>

    <p>
      <input type="submit"
      ng-disabled="myForm.user.$dirty && myForm.user.$invalid ||
      myForm.email.$dirty && myForm.email.$invalid">
    </p>

    </form>

    <script>
    var app = angular.module('myApp', []);
    app.controller('validateCtrl', function($scope) {
        $scope.user = 'John Doe';
        $scope.email = 'john.doe@gmail.com';
    });
    </script>

    </body>
    </html>


    HTML 表单属性 novalidate 用于禁用浏览器默认的验证。

     


    实例解析

    AngularJS ng-model 指令用于绑定输入元素到模型中。

     

    模型对象有两个属性: user 和 email

    我们使用了 ng-show指令, color:red 在邮件的 $dirty 或 $invalid 都为 true 时才显示。

    属性 描述
    $dirty 表单有填写记录
    $valid 字段内容合法的
    $invalid 字段内容是非法的
    $pristine 表单没有填写记录

     

    AngularJS API


    API 意为 Application Programming Interface(应用程序编程接口)。


    AngularJS 全局 API

    AngularJS 全局 API 用于执行常见任务的 JavaScript 函数集合,如:

    • 比较对象
    • 迭代对象
    • 转换对象

    全局 API 函数使用 angular 对象进行访问。

    以下列出了一些通用的 API 函数:

    API 描述
    angular.lowercase (<angular1.7)
    angular.$$lowercase()(angular1.7+)
    转换字符串为小写
    angular.uppercase() (<angular1.7)
    angular.$$uppercase()(angular1.7+)
    转换字符串为大写
    angular.isString() 判断给定的对象是否为字符串,如果是返回 true。
    angular.isNumber() 判断给定的对象是否为数字,如果是返回 true。

    注意:自 AngularJS 1.7 之后移除 angular.lowercase 和 angular.uppercase 方法, 改为 angular.$$lowercase 和 angular.$$uppercase


    angular.lowercase()

    实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.7.0/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="myCtrl">
    <p>{{ x1 }}</p>
    <p>{{ x2 }}</p>
    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function($scope) {
        $scope.x1 = "RUNOOB";
        $scope.x2 = angular.$$lowercase($scope.x1);
    });
    </script>

    </body>
    </html>

     

    angular.uppercase()

    实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.7.0/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="myCtrl">
    <p>{{ x1 }}</p>
    <p>{{ x2 }}</p>
    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function($scope) {
        $scope.x1 = "runoob";
        $scope.x2 = angular.$$uppercase($scope.x1);
    });
    </script>

    </body>
    </html>

     

    angular.isString()

    实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.7.0/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="myCtrl">
    <p>{{ x1 }}</p>
    <p>{{ x2 }}</p>
    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function($scope) {
        $scope.x1 = "RUNOOB";
        $scope.x2 = angular.isString($scope.x1);
    });
    </script>

    </body>
    </html>

     

    angular.isNumber()

    实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.7.0/angular.min.js"></script>
    </head>
    <body>

    <div ng-app="myApp" ng-controller="myCtrl">
    <p>{{ x1 }}</p>
    <p>{{ x2 }}</p>
    </div>

    <script>
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function($scope) {
        $scope.x1 = "RUNOOB";
        $scope.x2 = angular.isNumber($scope.x1);
    });
    </script>

    </body>
    </html>

     

    AngularJS Bootstrap


    AngularJS 的首选样式表是 Twitter Bootstrap, Twitter Bootstrap 是目前最受欢迎的前端框架。

     


    Bootstrap

    你可以在你的 AngularJS 应用中加入 Twitter Bootstrap,你可以在你的 <head>元素中添加如下代码:

    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">

    如果站点在国内,建议使用百度静态资源库的Bootstrap,代码如下:

    <link rel="stylesheet" href="//apps.bdimg.com/libs/bootstrap/3.3.4/css/bootstrap.min.css">

    以下是一个完整的 HTML 实例, 使用了 AngularJS 指令和 Bootstrap 类。

     


    HTML 代码

    <!DOCTYPE html>
    <html>
    <link rel="stylesheet" href="http://apps.bdimg.com/libs/bootstrap/3.3.4/css/bootstrap.min.css">
    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
    <body ng-app="myApp" ng-controller="userCtrl">

    <div class="container">

    <h3>Users</h3>

    <table class="table table-striped">
      <thead><tr>
        <th>Edit</th>
        <th>First Name</th>
        <th>Last Name</th>
      </tr></thead>
      <tbody><tr ng-repeat="user in users">
        <td>
          <button class="btn" ng-click="editUser(user.id)">
          <span class="glyphicon glyphicon-pencil"></span>&nbsp;&nbsp;Edit
          </button>
        </td>
        <td>{{ user.fName }}</td>
        <td>{{ user.lName }}</td>
      </tr></tbody>
    </table>

    <hr>
    <button class="btn btn-success" ng-click="editUser('new')">
      <span class="glyphicon glyphicon-user"></span> Create New User
    </button>
    <hr>

    <h3 ng-show="edit">Create New User:</h3>
    <h3 ng-hide="edit">Edit User:</h3>

    <form class="form-horizontal">
    <div class="form-group">
      <label class="col-sm-2 control-label">First Name:</label>
      <div class="col-sm-10">
        <input type="text" ng-model="fName" ng-disabled="!edit" placeholder="First Name">
      </div>
    </div> 
    <div class="form-group">
      <label class="col-sm-2 control-label">Last Name:</label>
      <div class="col-sm-10">
        <input type="text" ng-model="lName" ng-disabled="!edit" placeholder="Last Name">
      </div>
    </div>
    <div class="form-group">
      <label class="col-sm-2 control-label">Password:</label>
      <div class="col-sm-10">
        <input type="password" ng-model="passw1" placeholder="Password">
      </div>
    </div>
    <div class="form-group">
      <label class="col-sm-2 control-label">Repeat:</label>
      <div class="col-sm-10">
        <input type="password" ng-model="passw2" placeholder="Repeat Password">
      </div>
    </div>
    </form>

    <hr>
    <button class="btn btn-success" ng-disabled="error || incomplete">
      <span class="glyphicon glyphicon-save"></span> Save Changes
    </button>
    </div>

    <script src = "myUsers.js"></script>
    </body>
    </html>

     


    指令解析

    AngularJS 指令 描述
    <html ng-app 为 <html> 元素定义一个应用(未命名)
    <body ng-controller 为 <body> 元素定义一个控制器
    <tr ng-repeat 循环 users 对象数组,每个 user 对象放在 <tr> 元素中。
    <button ng-click 当点击 <button> 元素时调用函数 editUser()
    <h3 ng-show 如果 edit = true 显示 <h3> 元素
    <h3 ng-hide 如果 edit = true 隐藏 <h3> 元素
    <input ng-model 为应用程序绑定 <input> 元素
    <button ng-disabled 如果发生错误或者 incomplete = true 禁用 <button> 元素

     


    Bootstrap 类解析

    元素 Bootstrap 类 定义
    <div> container 内容容器
    <table> table 表格
    <table> table-striped 带条纹背景的表格
    <button> btn 按钮
    <button> btn-success 成功按钮
    <span> glyphicon 字形图标
    <span> glyphicon-pencil 铅笔图标
    <span> glyphicon-user 用户图标
    <span> glyphicon-save 保存图标
    <form> form-horizontal 水平表格
    <div> form-group 表单组
    <label> control-label 控制器标签
    <label> col-sm-2 跨越 2 列
    <div> col-sm-10 跨越 10 列

     


    JavaScript 代码

    myUsers.js

    angular.module('myApp', []).controller('userCtrl', function($scope) {
    $scope.fName = '';
    $scope.lName = '';
    $scope.passw1 = '';
    $scope.passw2 = '';
    $scope.users = [
    {id:1, fName:'Hege', lName:"Pege" },
    {id:2, fName:'Kim',  lName:"Pim" },
    {id:3, fName:'Sal',  lName:"Smith" },
    {id:4, fName:'Jack', lName:"Jones" },
    {id:5, fName:'John', lName:"Doe" },
    {id:6, fName:'Peter',lName:"Pan" }
    ];
    $scope.edit = true;
    $scope.error = false;
    $scope.incomplete = false; 

    $scope.editUser = function(id) {
      if (id == 'new') {
        $scope.edit = true;
        $scope.incomplete = true;
        $scope.fName = '';
        $scope.lName = '';
        } else {
        $scope.edit = false;
        $scope.fName = $scope.users[id-1].fName;
        $scope.lName = $scope.users[id-1].lName; 
      }
    };

    $scope.$watch('passw1',function() {$scope.test();});
    $scope.$watch('passw2',function() {$scope.test();});
    $scope.$watch('fName', function() {$scope.test();});
    $scope.$watch('lName', function() {$scope.test();});

    $scope.test = function() {
      if ($scope.passw1 !== $scope.passw2) {
        $scope.error = true;
        } else {
        $scope.error = false;
      }
      $scope.incomplete = false;
      if ($scope.edit && (!$scope.fName.length ||
      !$scope.lName.length ||
      !$scope.passw1.length || !$scope.passw2.length)) {
         $scope.incomplete = true;
      }
    };

    });

     


    JavaScript 代码解析

    Scope 属性 用途
    $scope.fName 模型变量 (用户名)
    $scope.lName 模型变量 (用户姓)
    $scope.passw1 模型变量 (用户密码 1)
    $scope.passw2 模型变量 (用户密码 2)
    $scope.users 模型变量 (用户的数组)
    $scope.edit 当用户点击创建用户时设置为true。
    $scope.error 如果 passw1 不等于 passw2 设置为 true
    $scope.incomplete 如果每个字段都为空(length = 0)设置为 true
    $scope.editUser 设置模型变量
    $scope.watch 监控模型变量
    $scope.test 验证模型变量的错误和完整性

     

    AngularJS 包含


    在 AngularJS 中,你可以在 HTML 中包含 HTML 文件。


    在 HTML 中包含 HTML 文件

    在 HTML 中,目前还不支持包含 HTML 文件的功能。


    服务端包含

    大多服务端脚本都支持包含文件功能 (SSI: Server Side Includes)。

    使用 SSI, 你可在 HTML 中包含 HTML 文件,并发送到客户端浏览器。

    PHP 实例

    <?php require("navigation.php"); ?>


    客户端包含

    通过 JavaScript 有很多种方式可以在 HTML 中包含 HTML 文件。

    通常我们使用 http 请求 (AJAX) 从服务端获取数据,返回的数据我们可以通过 使用 innerHTML 写入到 HTML 元素中。


    AngularJS 包含

    使用 AngularJS, 你可以使用 ng-include 指令来包含 HTML 内容:

    实例

    <!DOCTYPE html>
    <html>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    <body ng-app="">

    <div ng-include="'runoob.htm'"></div>

    </body>
    </html>

     

    步骤如下:


    runoob.htm 文件代码:

    <h1>菜鸟教程</h1>

    <p>这是一个被包含的 HTML 页面,使用 ng-include 指令来实现!</p>


    包含 AngularJS 代码

    ng-include 指令除了可以包含 HTML 文件外,还可以包含 AngularJS 代码:

    sites.htm 文件代码:

    <table>

    <tr ng-repeat="x in names">

    <td>{{ x.Name }}</td>

    <td>{{ x.Url }}</td>

    </tr>

    </table>

    包含的文件 "sites.htm" 中有 AngularJS 代码,它将被正常执行:

    实例

    <!DOCTYPE html>
    <html>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    <body>

    <div ng-app="myApp" ng-controller="sitesCtrl"> 
      <div ng-include="'sites.htm'"></div>
    </div>
     
    <script>
    var app = angular.module('myApp', []);
    app.controller('sitesCtrl', function($scope, $http) {
        $http.get("sites.php").then(function (response) {
            $scope.names = response.data.records;
        });
    });
    </script>

    <p>AngularJS 代码包含在 "sites.htm" 文件中。</p>

    </body>
    </html>

     


    跨域包含

    默认情况下, ng-include 指令不允许包含其他域名的文件。

    如果你需要包含其他域名的文件,你需要设置域名访问白名单:

    sites.htm 文件代码:

    <!DOCTYPE html>
    <html>
    <meta charset="utf-8">
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    <body ng-app="myApp">
     
    <div ng-include="'http://c.runoob.com/runoobtest/angular_include.php'"></div>
     
    <script>
    var app = angular.module('myApp', [])
    app.config(function($sceDelegateProvider) {
        $sceDelegateProvider.resourceUrlWhitelist([
            'http://c.runoob.com/runoobtest/**'
        ]);
    });
    </script>
    <p>你需要设置服务端允许跨域访问,设置方法可参考 <a target="_blank" href="/w3cnote/php-ajax-cross-border.html">PHP Ajax 跨域问题最佳解决方案</a>。
    </body>
    </html>

    此外,你还需要设置服务端允许跨域访问.

    angular_include.php 文件代码:

    <?php

    // 允许所有域名可以访问

    header('Access-Control-Allow-Origin:*');

    echo '<b style="color:red">我是跨域的内容</b>';

    ?>

     

    AngularJS 动画

    AngularJS 提供了动画效果,可以配合 CSS 使用。

    AngularJS 使用动画需要引入 angular-animate.min.js 库。

    <script src="http://cdn.static.runoob.com/libs/angular.js/1.4.6/angular-animate.min.js"></script>

    还需在应用中使用模型 ngAnimate:

    <body ng-app="ngAnimate">

    什么是动画?

    动画是通过改变 HTML 元素产生的动态变化效果。

    实例

    勾选复选框隐藏 DIV:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <style>
    div {
      transition: all linear 0.5s;
      background-color: lightblue;
      height: 100px;
      width: 100%;
      position: relative;
      top: 0;
      left: 0;
    }

    .ng-hide {
      height: 0;
      width: 0;
      background-color: transparent;
      top:-200px;
      left: 200px;
    }

    </style>
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular-animate.min.js"></script>
    </head>
    <body ng-app="ngAnimate">

    <h1>隐藏 DIV: <input type="checkbox" ng-model="myCheck"></h1>

    <div ng-hide="myCheck"></div>

    </body>
    </html>

    应用中动画不宜太多,但合适的使用动画可以增加页面的丰富性,也可以更易让用户理解。

     

    如果我们应用已经设置了应用名,可以把 ngAnimate 直接添加在模型中:

    实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <style>
    div {
      transition: all linear 0.5s;
      background-color: lightblue;
      height: 100px;
      width: 100%;
      position: relative;
      top: 0;
      left: 0;
    }

    .ng-hide {
      height: 0;
      width: 0;
      background-color: transparent;
      top:-200px;
      left: 200px;
    }

    </style>
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular-animate.min.js"></script>
    </head>
    <body ng-app="myApp">

    <h1>隐藏 DIV: <input type="checkbox" ng-model="myCheck"></h1>

    <div ng-hide="myCheck"></div>

    <script>
    var app = angular.module('myApp', ['ngAnimate']);
    </script>

    </body>
    </html>

     


    ngAnimate 做了什么?

    ngAnimate 模型可以添加或移除 class 。

    ngAnimate 模型并不能使 HTML 元素产生动画,但是 ngAnimate 会监测事件,类似隐藏显示 HTML 元素 ,如果事件发生 ngAnimate 就会使用预定义的 class 来设置 HTML 元素的动画。

    AngularJS 添加/移除 class 的指令:

    • ng-show
    • ng-hide
    • ng-class
    • ng-view
    • ng-include
    • ng-repeat
    • ng-if
    • ng-switch

    ng-show 和 ng-hide 指令用于添加或移除 ng-hide class 的值。

    其他指令会在进入 DOM 会添加 ng-enter 类,移除 DOM 会添加 ng-leave 属性。

    当 HTML 元素位置改变时,ng-repeat 指令同样可以添加 ng-move 类 。

    此外, 在动画完成后,HTML 元素的类集合将被移除。例如: ng-hide 指令会添加以下类:

    • ng-animate
    • ng-hide-animate
    • ng-hide-add (如果元素将被隐藏)
    • ng-hide-remove (如果元素将显示)
    • ng-hide-add-active (如果元素将隐藏)
    • ng-hide-remove-active (如果元素将显示)

    使用 CSS 动画

    我们可以使用 CSS transition(过渡) 或 CSS 动画让 HTML 元素产生动画效果


    CSS 过渡

    CSS 过渡可以让我们平滑的将一个 CSS 属性值修改为另外一个:

    实例

    在 DIV 元素设置了 .ng-hide 类时,过渡需要花费 0.5 秒,高度从 100px 变为 0:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <style>
    div {
      transition: all linear 0.5s;
      background-color: lightblue;
      height: 100px;
    }

    .ng-hide {
      height: 0;
    }
    </style>
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular-animate.min.js"></script>
    </head>
    <body ng-app="myApp">

    <h1>隐藏 DIV: <input type="checkbox" ng-model="myCheck"></h1>

    <div ng-hide="myCheck"></div>

    <script>
    var app = angular.module('myApp', ['ngAnimate']);
    </script>

    </body>
    </html>

     


    CSS 动画

    CSS 动画允许你平滑的修改 CSS 属性值:

    实例

    在 DIV 元素设置了 .ng-hide 类时, myChange 动画将执行,它会平滑的将高度从 100px 变为 0:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <style>
    @keyframes myChange {
      from {
          height: 100px;
      } to {
          height: 0;
      }
    }

    div {
      height: 100px;
      background-color: lightblue;
    }

    div.ng-hide {
      animation: 0.5s myChange;
    }
    </style>
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
    <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular-animate.min.js"></script>
    </head>
    <body ng-app="ngAnimate">

    隐藏 DIV: <input type="checkbox" ng-model="myCheck">

    <div ng-hide="myCheck">
    </div>


    </body>
    </html>

     

    AngularJS 依赖注入


    什么是依赖注入

    wiki 上的解释是:依赖注入(Dependency Injection,简称DI)是一种软件设计模式,在这种模式下,一个或更多的依赖(或服务)被注入(或者通过引用传递)到一个独立的对象(或客户端)中,然后成为了该客户端状态的一部分。

    该模式分离了客户端依赖本身行为的创建,这使得程序设计变得松耦合,并遵循了依赖反转和单一职责原则。与服务定位器模式形成直接对比的是,它允许客户端了解客户端如何使用该系统找到依赖

    一句话 --- 没事你不要来找我,有事我会去找你。

    AngularJS 提供很好的依赖注入机制。以下5个核心组件用来作为依赖注入:

    • value
    • factory
    • service
    • provider
    • constant

    value

    Value 是一个简单的 javascript 对象,用于向控制器传递值(配置阶段):

    // 定义一个模块
    var mainApp = angular.module("mainApp", []);
    
    // 创建 value 对象 "defaultInput" 并传递数据
    mainApp.value("defaultInput", 5);
    ...
    
    // 将 "defaultInput" 注入到控制器
    mainApp.controller('CalcController', function($scope, CalcService, defaultInput) {
       $scope.number = defaultInput;
       $scope.result = CalcService.square($scope.number);
       
       $scope.square = function() {
          $scope.result = CalcService.square($scope.number);
       }
    });

    factory

    factory 是一个函数用于返回值。在 service 和 controller 需要时创建。

    通常我们使用 factory 函数来计算或返回值。

    // 定义一个模块
    var mainApp = angular.module("mainApp", []);
    
    // 创建 factory "MathService" 用于两数的乘积 provides a method multiply to return multiplication of two numbers
    mainApp.factory('MathService', function() {
       var factory = {};
       
       factory.multiply = function(a, b) {
          return a * b
       }
       return factory;
    }); 
    
    // 在 service 中注入 factory "MathService"
    mainApp.service('CalcService', function(MathService){
       this.square = function(a) {
          return MathService.multiply(a,a);
       }
    });
    ...

    provider

    AngularJS 中通过 provider 创建一个 service、factory等(配置阶段)。

    Provider 中提供了一个 factory 方法 get(),它用于返回 value/service/factory。

    // 定义一个模块
    var mainApp = angular.module("mainApp", []);
    ...
    
    // 使用 provider 创建 service 定义一个方法用于计算两数乘积
    mainApp.config(function($provide) {
       $provide.provider('MathService', function() {
          this.$get = function() {
             var factory = {};  
             
             factory.multiply = function(a, b) {
                return a * b; 
             }
             return factory;
          };
       });
    });

    constant

    constant(常量)用来在配置阶段传递数值,注意这个常量在配置阶段是不可用的。

    mainApp.constant("configParam", "constant value");

    实例

    以下实例提供了以上几个依赖注入机制的演示。

    AngularJS 实例 - factory

    <html>
       
       <head>
          <meta charset="utf-8">
          <title>AngularJS  依赖注入</title>
       </head>
       
       <body>
          <h2>AngularJS 简单应用</h2>
          
          <div ng-app = "mainApp" ng-controller = "CalcController">
             <p>输入一个数字: <input type = "number" ng-model = "number" /></p>
             <button ng-click = "square()">X<sup>2</sup></button>
             <p>结果: {{result}}</p>
          </div>
          
          <script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
          
          <script>
             var mainApp = angular.module("mainApp", []);
             mainApp.value("defaultInput", 5);
             
             mainApp.factory('MathService', function() {
                var factory = {};
                
                factory.multiply = function(a, b) {
                   return a * b;
                }
                return factory;
             });
             
             mainApp.service('CalcService', function(MathService){
                this.square = function(a) {
                   return MathService.multiply(a,a);
                }
             });
             
             mainApp.controller('CalcController', function($scope, CalcService, defaultInput) {
                $scope.number = defaultInput;
                $scope.result = CalcService.square($scope.number);

                $scope.square = function() {
                   $scope.result = CalcService.square($scope.number);
                }
             });
                
          </script>
          
       </body>
    </html>

     

    AngularJS 实例 - provider

    <html>
       
       <head>
          <meta charset="utf-8">
          <title>AngularJS  依赖注入</title>
       </head>
       
       <body>
          <h2>AngularJS 简单应用</h2>
          
          <div ng-app = "mainApp" ng-controller = "CalcController">
             <p>输入一个数字: <input type = "number" ng-model = "number" /></p>
             <button ng-click = "square()">X<sup>2</sup></button>
             <p>结果: {{result}}</p>
          </div>
          
          <script src="http://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
          
          <script>
             var mainApp = angular.module("mainApp", []);
             
             mainApp.config(function($provide) {
                $provide.provider('MathService', function() {
                   this.$get = function() {
                      var factory = {};
                      
                      factory.multiply = function(a, b) {
                         return a * b;
                      }
                      return factory;
                   };
                });
             });
                
             mainApp.value("defaultInput", 5);
             
             mainApp.service('CalcService', function(MathService){
                this.square = function(a) {
                   return MathService.multiply(a,a);
                }
             });
             
             mainApp.controller('CalcController', function($scope, CalcService, defaultInput) {
                $scope.number = defaultInput;
                $scope.result = CalcService.square($scope.number);

                $scope.square = function() {
                   $scope.result = CalcService.square($scope.number);
                }
             });
                
          </script>
          
       </body>
    </html>

     

    AngularJS 路由

    本章节我们将为大家介绍 AngularJS 路由。

    AngularJS 路由允许我们通过不同的 URL 访问不同的内容。

    通过 AngularJS 可以实现多视图的单页 Web 应用(single page web application,SPA)。

    通常我们的 URL 形式为 http://runoob.com/first/page,但在单页 Web 应用中 AngularJS 通过 #! + 标记 实现,例如:

    http://runoob.com/#!/first
    http://runoob.com/#!/second
    http://runoob.com/#!/third

    注意 Angular1.6 之前的版本是通过 # + 标记 实现路由。

    当我们点击以上的任意一个链接时,向服务端请的地址都是一样的 (http://runoob.com/)。 因为 #! 号之后的内容在向服务端请求时会被浏览器忽略掉。 所以我们就需要在客户端实现 #! 号后面内容的功能实现。 AngularJS 路由就通过 #! + 标记 帮助我们区分不同的逻辑页面并将不同的页面绑定到对应的控制器上。

    在以上图形中,我们可以看到创建了两个 URL: /ShowOrders 和 /AddNewOrder。每个 URL 都有对应的视图和控制器。

    接下来我们来看一个简单的实例:

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>AngularJS 路由实例 --angularjs教程</title>
    <script src="https://cdn.staticfile.org/angular.js/1.7.0/angular.min.js"></script>
    <script src="https://cdn.staticfile.org/angular.js/1.7.0/angular-route.min.js"></script>
    </head>
    <body ng-app='routingDemoApp'>
     
        <h2>AngularJS 路由应用</h2>
        <ul>
            <li><a href="#!/">首页</a></li>
            <li><a href="#!/computers">电脑</a></li>
            <li><a href="#!/printers">打印机</a></li>
            <li><a href="#!/blabla">其他</a></li>
        </ul>
         
        <div ng-view></div>
        <script>
            angular.module('routingDemoApp',['ngRoute'])
            .config(['$routeProvider', function($routeProvider){
                $routeProvider
                .when('/',{template:'这是首页页面'})
                .when('/computers',{template:'这是电脑分类页面'})
                .when('/printers',{template:'这是打印机页面'})
                .otherwise({redirectTo:'/'});
            }]);
        </script>
    </body>
    </html>

    实例解析:

    • 1、载入了实现路由的 js 文件:angular-route.js。

    • 2、包含了 ngRoute 模块作为主应用模块的依赖模块。

      angular.module('routingDemoApp',['ngRoute'])
    • 3、使用 ngView 指令。

      <div ng-view></div>

      该 div 内的 HTML 内容会根据路由的变化而变化。

    • 4、配置 $routeProvider,AngularJS $routeProvider 用来定义路由规则。

      module.config(['$routeProvider', function($routeProvider){
          $routeProvider
              .when('/',{template:'这是首页页面'})
              .when('/computers',{template:'这是电脑分类页面'})
              .when('/printers',{template:'这是打印机页面'})
              .otherwise({redirectTo:'/'});
      }]);

    AngularJS 模块的 config 函数用于配置路由规则。通过使用 configAPI,我们请求把$routeProvider注入到我们的配置函数并且使用$routeProvider.whenAPI来定义我们的路由规则。

    $routeProvider 为我们提供了 when(path,object) & otherwise(object) 函数按顺序定义所有路由,函数包含两个参数:

    • 第一个参数是 URL 或者 URL 正则规则。
    • 第二个参数是路由配置对象。

    路由设置对象

    AngularJS 路由也可以通过不同的模板来实现。

    $routeProvider.when 函数的第一个参数是 URL 或者 URL 正则规则,第二个参数为路由配置对象。

     

    路由配置对象语法规则如下:

    $routeProvider.when(url, {
        template: string,
        templateUrl: string,
        controller: string, function 或 array,
        controllerAs: string,
        redirectTo: string, function,
        resolve: object<key, function>
    });

    参数说明:

    • template:

      如果我们只需要在 ng-view 中插入简单的 HTML 内容,则使用该参数:

      .when('/computers',{template:'这是电脑分类页面'})
    • templateUrl:

      如果我们只需要在 ng-view 中插入 HTML 模板文件,则使用该参数:

      $routeProvider.when('/computers', {
          templateUrl: 'views/computers.html',
      });

      以上代码会从服务端获取 views/computers.html 文件内容插入到 ng-view 中。

    • controller:

      function、string或数组类型,在当前模板上执行的controller函数,生成新的scope。

    • controllerAs:

      string类型,为controller指定别名。

    • redirectTo:

      重定向的地址。

    • resolve:

      指定当前controller所依赖的其他模块。

    实例

    AngularJS 实例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>AngularJS 路由实例 - 菜鸟教程</title>
    <script src="https://cdn.staticfile.org/angular.js/1.7.0/angular.min.js"></script>
    <script src="https://cdn.staticfile.org/angular.js/1.7.0/angular-route.min.js"></script>
    <script type="text/javascript">
    angular.module('ngRouteExample', ['ngRoute'])
    .controller('HomeController', function ($scope, $route) { $scope.$route = $route;})
    .controller('AboutController', function ($scope, $route) { $scope.$route = $route;})
    .config(function ($routeProvider) {
        $routeProvider.
        when('/home', {
            templateUrl: 'embedded.home.html',
            controller: 'HomeController'
        }).
        when('/about', {
            templateUrl: 'embedded.about.html',
            controller: 'AboutController'
        }).
        otherwise({
            redirectTo: '/home'
        });
    });
    </script>

      
    </head>

    <body ng-app="ngRouteExample" class="ng-scope">
      <script type="text/ng-template" id="embedded.home.html">
          <h1> Home </h1>
      </script>

      <script type="text/ng-template" id="embedded.about.html">
          <h1> About </h1>
      </script>

      <div> 
        <div id="navigation">  
          <a href="#!/home">Home</a>
          <a href="#!/about">About</a>
        </div>
          
        <div ng-view="">
        </div>
      </div>
    </body>
    </html>

     

    AngularJS 应用


    现在是时候创建一个真正的 AngularJS 单页 Web 应用(single page web application,SPA)了。


    AngularJS 应用实例

    您已经学习了足够多关于 AngularJS 的知识,现在可以开始创建您的第一个 AngularJS 应用程序:

    我的笔记


    应用程序讲解

    AngularJS 实例

    <html ng-app="myNoteApp">
    <head>
    <meta charset="utf-8">
    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
    </head>
    <body>

    <div ng-controller="myNoteCtrl">

    <h2>我的笔记</h2>

    <p><textarea ng-model="message" cols="40" rows="10"></textarea></p>

    <p>
    <button ng-click="save()">保存</button>
    <button ng-click="clear()">清除</button>
    </p>

    <p>Number of characters left: <span ng-bind="left()"></span></p>

    </div>

    <script src="myNoteApp.js"></script>
    <script src="myNoteCtrl.js"></script>

    </body>
    </html>

     

    应用程序文件 "myNoteApp.js":

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

    控制器文件 "myNoteCtrl.js":

    app.controller("myNoteCtrl", function($scope) {
        $scope.message = "";
        $scope.left  = function() {return 100 - $scope.message.length;};
        $scope.clear = function() {$scope.message = "";};
        $scope.save  = function() {alert("Note Saved");};
    });

    <html> 元素是 AngularJS 应用: ng-app="myNoteApp" 的容器:

    <html ng-app="myNoteApp">

    <div> 是 HTML 页面中控制器: ng-controller="myNoteCtrl" 的作用域:

    <div ng-controller="myNoteCtrl">

    ng-model 指令绑定了 <textarea> 到控制器变量 message:

    <textarea ng-model="message" cols="40" rows="10"></textarea>

    两个 ng-click 事件调用了控制器函数 clear() 和 save():

    <button ng-click="save()">Save</button>
    <button ng-click="clear()">Clear</button>

    ng-bind 指令绑定控制器函数 left() 到<span> ,用于显示剩余字符:

    Number of characters left: <span ng-bind="left()"></span>

    应用库文件需要在 AngularJs 加载后才能执行:

    <script src="myNoteApp.js"></script>
    <script src="myNoteCtrl.js"></script>


    AngularJS 应用架构

    以上实例是一个完整的 AngularJS 单页Web应用(single page web application,SPA)。

    <html> 元素包含了 AngularJS 应用 (ng-app=)。

    <div> 元素定义了 AngularJS 控制器的作用域 (ng-controller=)。

    在一个应用可以有很多控制器。

    应用文件(my...App.js) 定义了应用模型代码。

    一个或多个控制器文件 (my...Ctrl.js) 定义了控制器代码。


    总结 - 它是如何工作的呢?

    ng-app 指令位于应用的根元素下。

    对于单页Web应用(single page web application,SPA),应用的根通常为 <html> 元素。

    一个或多个 ng-controller 指令定义了应用的控制器。每个控制器有他自己的作用域:: 定义的 HTML 元素。

    AngularJS 在 HTML DOMContentLoaded 事件中自动开始。如果找到 ng-app 指令 , AngularJS 载入指令中的模块,并将 ng-app 作为应用的根进行编译。

    应用的根可以是整个页面,或者页面的一小部分,如果是一小部分会更快编译和执行。

     

     

     

     

     

     

     

    展开全文
  • AngularJS极速入门

    万人学习 2018-10-22 21:38:10
    本课程由King老师精心打造的AngularJS极速入门课程,内容包括AngularJS简介、基本概念与用法实例、核心原理解析等。是前端进阶技能! 山哥出品,必属精品!
  • AngularJS

    千次阅读 2018-10-08 11:07:21
    1.AngularJS是一个用于设计动态web应用的js框架 2.它不仅仅是一个javascript框架,因为它的核心其实是对HTML标签的增强 3.能够用标签完成一部分页面逻辑,具体方式就是通过自定义标签、自定义属性等,这些HTML原生...

    在这里插入图片描述
    在这里插入图片描述

    一、基本概念

    1.AngularJS是一个用于设计动态web应用的js框架
    2.它不仅仅是一个javascript框架,因为它的核心其实是对HTML标签的增强
    3.能够用标签完成一部分页面逻辑,具体方式就是通过自定义标签、自定义属性等,这些HTML原生没有的标签/属性在ng中有一个名字:指令(directive)
    4.你不用再“直接”操控DOM,只要给你的DOM注上metadata(即AngularJS里的directive们),然后让AngularJS来帮你操纵DOM
    5.AngularJS不依赖(也不妨碍)任何其他的框架。你甚至可以基于其它的框架来开发AngularJS应用
    6.开发的是单页应用,AngularJS就是你的上上之选,但是像游戏开发之类对DOM进行大量操纵、又或者单纯需要 极高运行速度的应用,就不是AngularJS的用武之地了

    二、基本指令

    1.ng-app

    指令标记了AngularJS脚本的作用域(angularJS从ng-app开始启动的,在任意的一个单页angularJS应用里面,ng-app只能有一个)(一般值为 myModule )
    
    js文件中:angular.module("myApp",[],function(){ });
    

    2.ng-contorller

    定义了应用程序控制器。控制器是 JavaScript 对象,由标准的 JavaScript 对象的构造函数创建   
    
    js文件中:  myApp.controller("myCtrl",[一连串注入的东西, function(前面一连串注入的东西){控制器的业务逻辑代码 }]);
    

    3.ng-model

    把元素值(比如输入域的值)绑定到应用程序                   
    
    js文件中: $scope.数据
    

    4.ng-bind

    把应用程序数据绑定到 HTML 视图({{ }}  首页建议不这样用,建议用ng-bind)   
    
    js文件中: $scope.数据
    

    5.ng-init

    初始化应用程序数据,中间用分号来分隔。通常情况下,不使用 ng-init。将使用一个控制器或模块来代替它
    

    6.ng-repeat

    会重复一个 HTML 元素(集合必须是数组或对象)
    
    1)提供在html模板中的变量
    
        (1)$index     当前索引
    
        (2)$first     是否为头元素
    
        (3)$middle    是否为非头非尾元素
    
        (4)$last    是否为尾元素
    
    2)如何循环集合
    
        (1)数组    x in records
    
        (2)对象    (key, value) in myObj
    

    7.事件指令

    1)ng-click
    
    2)ng-dblclick
    
    3)ng-change
    
    4)ng-mousedown
    
    5)ng-mouseenter
    
    6)ng-mouseleave
    
    7)ng-mousemove
    
    8)ng-mouseover
    
    9)ng-mouseup
    
    10)ng-submit
    

    8.表单(form)指令

    1) 除去对象的方法与属性,form 这个标签本身有一些动态类可以使用
    
        (1)ng-valid         当表单验证通过时的设置
    
        (2)ng-invalid     当表单验证失败时的设置
    
        (3)ng-pristine     表单的未被动之前拥有
    
        (4)ng-dirty         表单被动过之后拥有
    
    2)form对象的属性
    
        (1)$pristine         表单是否未被动过
    
        (2)$dirty         表单是否被动过
    
        (3)$valid         表单是否验证通过
    
        (4)$invalid         表单是否验证失败
    
        (5)$error         表单的验证错误
    
    3)其他表单控件相关指令
    
        (1)ng-required     是否必填
    
        (2)ng-minlength     最小长度
    
        (3)ng-maxlength     最大长度
    
        (4)ng-pattern     匹配模式
    
        (5)ng-change         值变化时的回调
    
        (6)ng-options        用于select标签下的数据呈现
    
        (7)ng-true-value、ng-false-value  选中与不选中的值
    
    4)指令的取值均为 boolean 类型
    
        (1)ng-checked     控制 radio 和 checkbox 的选中状态
    
        (2)ng-selected     控制下拉框的选中状态
    
        (3)ng-disabled     控制失效状态
    
        (4)ng-multiple     控制多选
    
        (5)ng-readonly     控制只读状态
    
        (6)ng-src         src 属性( img等)
    
        (7)ng-href        href 属性(a标签等)
    
        (8)ng-include        div引入其他视图    <div ng-include src="'static/view/common/sidebar.html'"></div>
    

    三、angularJS作用域

    1.$rootScope(可以作用在 ng-app 指令包含的所有 HTML 元素中)
    1) $rootScope 可作用于整个应用中。是各个 controller 中 scope 的桥梁。
    
    2) 用 $rootScope 定义的值,可以在各个 controller 中使用
    
    2.Scope(Scope(scope是一个把view(一个DOM元素)连结到controller上的对象)
    1) $scope 实际上就是一个JavaScript对象,controller和view都可以访问它,所以我们可以利用它在两者间传递信息
    
    2) 这个 $scope 对象里,我们既存储数据,又存储将要运行在view上的函数
    
    3) $scope的生命周期
    
        创建---->注册监控---->检测模型的变化---->观察模型有没有“脏”---->自动销毁   
    
    3.AngularJS中会创建作用域的指令
    1)ng-include       创建一个新的子作用域,并且会继承父作用域
    
    2)ng-switch        创建一个新的子作用域,并且会继承父作用域
    
    3) ng-repeat        为每一个item都创建一个子作用域,全部都会继承父作用域
    
    4) ng-controller    创建一个新的作用域,并且会继承父作用域。
    
    5) 自定义指令       这个要看scope属性如何设置,默认scope为false,不会创建新的Scope,如果设置为true,那么会创建一个子Scope并且继承父Scope,除了true和false以外,还可以将scope属性设置为一个对象,这样将会创建一个隔离作用域,这会使指令的模板无法访问外部作用域
    
    4.$scope生命周期
    1) 创建           
    
        (1)在创建控制器或指令时,AngularJS会用$injector创建一个新的作用域,并在这个新建的控制器或指令运行时将作用域传递进去
    
    2)链接
    
        (1)当Angular开始运行时,所有的$scope对象都会附加或者链接到视图中
    
        (2)这些作用域将会注册当Angular应用上下文中发生变化时所需要运行的函数。这些函数被称为$watch函数,Angular通过这些函数获知何时启动事件循环
    
    3)更新
    
        (1)当事件循环运行时,它通常执行在$rootScope上。每个子作用域都执行自己的脏值检测,每个监控函数都会检查变化
    
        (2)如果检测到任意变化,$scope对象就会触发指定的回调函数
    
    4)销毁
    
        (1)当一个$scope在视图中不再需要时,这个作用域将会清理和销毁自己
    
        (2)基本上不会需要你来清理作用域,但是你还是可以使用$scope上的$destroy()方法来清理作用域
    

    四、部分特性

    1.MVVC(数据双向绑定)

    1)利用双向数据绑定,不仅能把数据模型的变化同步到视图上面,还可以利用双向数据绑定的特性来做一些样式上面的控制
    
    2)通过数据与模板的绑定,能够让我们摆脱繁琐的DOM操作,而将注意力集中在业务逻辑上
    
    3)在AngularJS中,一个模板就是一个HTML文件
    
    4)样式控制
    
        (1)ng-class(给元素绑定类名)
    
             <div ng-class="{error:isError,warning:isWarning}">{{messageTest}}</div>
    
            {error:isError,warning:isWarning}  :这是一个表达式,如果isError的值为true,就会用error的样式;如果isWarning的值是true,就会用warning的值
    
        (2)样式的显示和隐藏——ng-show和ng-hide
    
        (3)ng-style(ng-style用来绑定元素的css样式,其表达式的返回值为一个js对象,键为css样式名,值为该样式对应的合法取值)
    
            例如:<div ng-style="{color:'red'}">ng-style测试</div>        $scope.style = {color:'red'};
    
    5)模板中可以使用的东西包括以下四种
    
        (1)指令(directive)        ng提供的或者自定义的标签和属性,用来增强HTML表现力
    
        (2)标记(markup)           即双大括号{{}},可将数据单向绑定到HTML中
    
        (3)过滤器(filter)         用来格式化输出数据
    
        (4)表单控制               用来增强表单的验证功能
    

    2.模块

    1)通过 AngularJS 的 angular.module 函数来创建模块
    
    2)模块定义了一个应用程序
    
    3)模块是应用程序中不同部分的容器。相当于一个集合
    
    4)模块是应用控制器的容器
    
    5)控制器通常属于一个模块
    
    注意:在多个 AngularJS 实例中,将看到 AngularJS 库是在文档的 <head> 区域被加载
          在实例中,AngularJS 在 <head> 元素中被加载,因为对 angular.module 的调用只能在库加载完成后才能进行
    
    

    3.依赖注入

    1)当我们需要使用某一模块或服务时,不需要关心此模块内部如何实现,只需声明一下就可以使用了。在多处使用只需进行多次声明,大大提高可复用性
    
    2)需要的地方进行声明,由框架来替我们注入
    
    3)如果想用别名,那要显示注入 如: app.controller('testC',['$scope','remoteData',function($scope,rd){  },顺序要一样 ,我们一般名称一样也显示注入
    

    五、服务(系统内置的服务以$开头)

    1.AngularJS服务是一个单例对象或函数,对外提供特定的功能
    2.是一个单例,即无论这个服务被注入到任何地方,对象始终只有一个实例
    3.自定义服务
    1)内置的$provide服务
    
        (1)var app = angular.module('MyApp', [], function($provide) {
    
                $provide.factory('remoteData', function() {
    
                 var data = {name:'n',value:'v'};
    
                    return data;
    
                });
    
            });
    
    2)Module的factory方法
    
        (1)app.factory('remoteData',function(){
    
                    var data = {name:'n',value:'v'};
    
                    return data;
    
             });
    
    3)Module的service方法
    
        (1)app.service('remoteData',function(){
    
                    this.name = 'n';
    
                    this.value = 'v';
    
            });
    
    4)区别
    
        (1)Module的factory和$provide的factory方法是一模一样的,从官网文档看它们其实就是一回事
    
        (2)Module的service方法,它没有return任何东西,是因为service方法本身返回一个构造器,系统会自动使用new关键字来创建出一个对象。所以我们看到在构造器函数内可以使用this,这样调用该服务的地方便可以直接通过remoteData.name来访问数据了
    
    4.常用内置服务
    1)$location服务(暴露浏览器地址栏中的URL,与浏览器同步URL)
    
        (1)absUrl( )        只读;根据在RFC 3986中指定的规则,返回url,带有所有的片段
    
        (2)path( )          读、写;当没有任何参数时,返回当前url的路径;当带有参数时,改变路径,并返回$location。(返回的路径永远会带有/)
    
        (3)host( )          只读;返回url中的主机路径
    
    2)$q服务(是AngularJS中自己封装实现的一种Promise实现,Promise是一种异步处理模式)
    
        (1)常用方法
    
            a.defer()        创建一个deferred对象,这个对象可以执行几个常用的方法,比如resolve,reject,notify
    
            b.all()          传入Promise的数组,批量执行,返回一个promise对象
    
            c.when()         传入一个不确定的参数,如果符合Promise标准,就返回一个promise对象
    
        (2)在Promise中,定义了三种状态:等待状态,完成状态,拒绝状态
    
        (3)关于状态有几个规定
    
            a.状态的变更是不可逆的
    
            b.等待状态可以变成完成或者拒绝
    
        (4)使用resolve方法,变成完成状态;使用reject方法,变成拒绝状态
    
        (5)示例:
    
            var defer1 = $q.defer();             // defer()用于创建一个deferred对象,声明延后执行
            var promise1 = defer1.promise        // defer.promise用于返回一个promise对象,来定义then方法
    
            promise1                             // then中有三个参数,分别是成功回调、失败回调、状态变更回调
                .then(a,b,c)
                .then(a,b,c)
                .then(a,b,c)
                .catch()
                .finally()
    
             defer1.resolve("hello");            // resolve中传入的变量或者函数返回结果,会当作第一个then方法的参数
            // defer1.reject("sorry,reject");
    
    

    六、过滤器

    1.作用就是接收一个输入,通过某个规则进行处理,然后返回处理后的结果,主要用在数据的格式化上
    2.filter的两种使用方法
    1)在模板(html)中使用filter
    
        (1)直接在{{}}中使用filter,跟在表达式后面用 | 分割           
    
            例如:{{ expression | filter }}
    
        (2)也可以多个filter连用,上一个filter的输出将作为下一个filter的输入   
    
            例如:{{ expression | filter1 | filter2 | ... }}
    
        (3)filter可以接收参数,参数用 : 进行分割               
    
            例如:{{ expression | filter:argument1:argument2:... }}
    
        (4)除了对{{}}中的数据进行格式化,我们还可以在指令中使用filter,例如先对数组array进行过滤处理,然后再循环输出
    
            例如:<span ng-repeat="a in array | filter ">
    
    2)在controller和service中使用filter
    
        (1)js代码中也可以使用过滤器,方式就是我们熟悉的依赖注入
    
            例如:app.controller('testC',function($scope,currencyFilter){
                       $scope.num = currencyFilter(123534); 
                   }
                  在模板中使用{{num}}就可以直接输出$123,534.00了,ps:在服务中也一样
    
        (2)controller中使用多个filter,只需注入一个$filter就够了
    
            例如:app.controller('testC',function($scope,$filter){
                       $scope.num = $filter('currency')(123534);
                             $scope.date = $filter('date')(new Date()); 
                  }
    
    
    3.内置过滤器
    1)currency (货币处理)
    
        (1)使用currency可以将数字格式化为货币,默认是美元符号,也可以自己传入所需的符号
    
            {{num | currency : '¥'}}
    
    2)date (日期格式化)
    
        (1){{date | date : 'yyyy-MM-dd hh:mm:ss EEEE'}}
    
        (2)y M d h m s E 分别表示 年 月 日 时 分 秒 星期,可以自由组合它们
    
    3)filter(匹配子串)
    
        (1)用来处理一个数组,然后可以过滤出含有某个子串的元素,作为一个子数组来返回
    
        (2)可以是字符串数组,也可以是对象数组。如果是对象数组,可以匹配属性的值
    
        (3){{ childrenArray | filter : 'a' }}                   // 匹配属性值中含有a的
    
        (4){{ childrenArray | filter : {name : 'i'} }}          // 参数是对象,匹配name属性中含有i的
    
        (5){{childrenArray | filter : func }}                   // 参数是函数,指定返回age>4的
              $scope.func = function(e){return e.age>4;}
    
    4)json(格式化json对象)
    
        (1)json过滤器可以把一个js对象格式化为json字符串,没有参数
    
    5)limitTo(限制数组长度或字符串长度)
    
        (1)limitTo过滤器用来截取数组或字符串,接收一个参数用来指定截取的长度,如果参数是负值,则从数组尾部开始截取
    
        (2){{ childrenArray | limitTo : 2 }}                    // 将会显示数组中的前两项
    
    6) lowercase(小写)
    
        (1)把数据转化为全部小写
    
    7)uppercase(大写)
    
        (2)把数据转化为全部大写
    
    8)number(格式化数字)
    
        (1)number过滤器可以为一个数字加上千位分割,像这样,123,456,789,同时接收一个参数,可以指定float类型保留几位小数
    
        (2){{ num | number : 2 }}
    
    9)orderBy(排序)
    
        (1)可以将一个数组中的元素进行排序
    
        (2)接收一个参数来指定排序规则,参数可以是一个字符串,表示以该属性名称进行排序
    
            例如:<div>{{ childrenArray | orderBy : 'age' }}</div>             // 按age属性值进行排序,若是-age,则倒序
    
        (3)可以是一个函数,定义排序属性。
    
            例如:<div>{{ childrenArray | orderBy : orderFunc }}</div>         // 按照函数的返回值进行排序
    
        (4)还可以是一个数组,表示依次按数组中的属性值进行排序(若按第一项比较的值相等,再按第二项比较)
    
            例如:<div>{{ childrenArray | orderBy : ['age','name'] }}</div>    // 如果age相同,按照name进行排序
    
    4.自定义过滤器
    1)使用module的filter方法,返回一个函数,该函数接收输入值,并返回处理后的结果
    
    2)实例:
    
        app.filter('odditems',function(){
                return function(inputArray){
                    var array = [];
                    for(var i=0;i<inputArray.length;i++){
                            if(i%2!==0){
                                array.push(inputArray[i]);
                            }
                    }
                    return array;
                }
        });
    

    七、自定义指令

    1.指令在框架中的执行流程
    1)浏览器得到 HTML 字符串内容,解析得到 DOM 结构
    
    2)ng 引入,把 DOM 结构扔给 $compile 函数处理
    
        (1)找出 DOM 结构中有变量占位符
    
        (2)匹配找出 DOM 中包含的所有指令引用
    
        (3)把指令关联到 DOM
    
        (4)关联到 DOM 的多个指令按权重排列
    
        (5)执行指令中的 compile 函数(改变 DOM 结构,返回 link 函数)
    
        (6)得到的所有 link 函数组成一个列表作为 $compile 函数的返回
    
    3)执行 link 函数(连接模板的 scope)
    
    2.指令的几种使用方式(常用的就是作为标签和属性)
    1)作为标签(E):    <my-dir></my-dir>       
    
    2)作为属性(A):    <span my-dir="exp"></span>
    
    3)作为注释(M):    <!-- directive: my-dir exp -->
    
    4)作为类名(C):    <span class="my-dir: exp;"></span>
    
    注意:(1)千万不要用ng-前缀了,防止与系统自带的指令重名
    
          (2)指令命名时用驼峰规则,使用时用-分割各单词,如:定义myDirective
    
    3.自定义指令的配置参数
    1)restrict: string      指令的使用方式,包括标签,属性,类,注释
    
    2)priority: number      指令执行的优先级
    
    3)template:string      指令使用的模板,用HTML字符串的形式表示
    
    4)templateUrl: string   从指定的url地址加载模板
    
    5)replace:bool         是否用模板替换当前元素,若为false,则append在当前元素上
    
    6)transclude:bool      是否将当前元素的内容转移到模板中
    
    7)scope: bool or object 指定指令的作用域
    
    8)controller: function controllerConstructor($scope, $element, $attrs, $transclude){...},
    
       定义与其他指令进行交互的接口函数
    
    9)re require: string    指定需要依赖的其他指令
    
    10)link: function postLink(scope, iElement, iAttrs) {...}
    
        以编程的方式操作DOM,包括添加监听器等
    
    11)compile: function compile(tElement, tAttrs, transclude){
    
                 return: {
    
                        pre: function preLink(scope, iElement, iAttrs, controller){...},
    
                        post: function postLink(scope, iElement, iAttrs, controller){...}
    
                }
    
    
        编程的方式修改DOM模板的副本,可以返回链接函数
    
    4.实例:
    var app = angular.module('MyApp', [], function(){console.log('here')});
    
    app.directive('sayHello',function(){
               return {
                        restrict : 'E',
                        template : '<div>hello</div>'
               };
         })
    
    5.compile和link的区别

    八、$http

    1.常用配置项:
    1)method     方法
    
    2)url         路径
    
    3)params     GET请求的参数
    
    4)data     post请求的参数
    
    5)headers     头
    

    2.实例

    $http.get({url:"/xxx.action"}).success(function(data){
            alert(data);
    }).error(function(){
            alert("error");
    });
    
    

    九、路由

    1.基本常识
    1)ngRoute:不同视图之间进行切换    (html中引入 <div ng-view=""></div> )
    
    2)$routeProvider用于在主应用主模块的配置方法中。$route与$routeParams一般常见于控制器中
    
    3)通过 AngularJS 可以实现多视图的单页Web应用(single page web application,SPA)
    
    4)ngRoute并没有在AngularJS的核心包里面,所以在使用的时候,需要引入一个独立的库
    
    5)原生路由的缺点:无法进行深层次的嵌套路由。使用angular-UI中的UI-Router就可以解决
    
    6)当我们点击以上的任意一个链接时,向服务端请的地址都是一样的 (http://runoob.com/)。 因为 # 号之后的内容在向服务端请求时会被浏览器忽略掉
    
    7)AngularJS 模块的 config 函数用于配置路由规则
    
    
    2.ng的路由(ngRoute)是一个单独的模块,包含以下内容
    1)服务 $routeProvider         用来定义一个路由表,即地址栏与视图模板的映射
    
    2)服务 $routeParams           保存了地址栏中的参数,例如 {id : 1, name : 'tom'},允许你检索当前路由的参数
    
    3)服务 $route                 完成路由匹配,并且提供路由相关的属性访问及事件,如访问当前路由对应的 controller
    
    4)指令 ngView                 用来在主视图中指定加载子视图的区域    (html中引入 <div ng-view=""></div> )
    
    3.定义路由
    1)引入文件和依赖
    
        (1)ngRoute 也是一个附件模块,故需要在页面上引入 angular-route.min.js
    
        (2)并在模块中注入对 ngRoute 的依赖,var app = angular.module('MyApp', ['ngRoute']);
    
    2)定义路由表
    
        (1)$routeProvider提供了定义路由表的服务,它有两个核心方法,when(path,route)和otherwise(params)
    
        (2)when(path,route)方法接收两个参数,path是一个string类型,表示该条路由规则所匹配的路径,它将与地址栏的内容($location.path)值进行匹配
    
            a.第一个参数是 URL 或者 URL 正则规则
    
            b.第二个参数是路由配置对象
    
    
        (3)route参数是一个object,用来指定当path匹配后所需的一系列配置项
    
            a.controller        在当前模板上执行的controller函数,生成新的scope
    
            b.controllerAs      为controller指定别名
    
            c.template          视图所用的模板,这部分内容将被ngView引用
    
            d.templateUrl       当视图模板为单独的html文件或是使用了<script type="text/ng-template">定义模板时使用
    
            f.resolve           指定当前controller所依赖的其他模块
    
            g.redirectTo        重定向的地址
    
    3) 在主视图模板中指定加载子视图的位置
    
        <div ng-view></div>     或者    <ng-view></ng-view>
    
    4)示例:
    
        demoApp.config(['$routeProvider',function($routeProvider) { 
    
            $routeProvider.when('/list', { 
    
                        templateUrl: 'route/list.html', 
    
                          controller: 'routeListController'
    
                         }).when('/list/:id', { 
    
                          templateUrl: 'route/detail.html',
    
                           controller: 'routeDetailController'
    
                      }).otherwise({ 
    
                            redirectTo: '/list' 
    
                         }); 
    
            }]);
    
    4.angular-UI中的UI-Router
    1)UI-Router是Angular-UI提供的客户端路由框架,它解决了原生的ng-route的很多不足,可以视图嵌套(这个我还需要好好揣摩区别)
    
    2)示例
    
        (1)引入               <script src="angular-ui-router/release/angular-ui-router.js"></script>
    
        (2)声明模块以及依赖   var app = angular.module('myApp', ['ui.router']);
    
        (3)Html中引入         <div ui-view></div>
    
        (4)app.config中配置   
    
                app.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider){
                    $urlRouterProvider.otherwise("/home");
                    $stateProvider.state('home', angularAMD.route({
                        url: '/home',
                        templateUrl: 'static/view/usercenter/forstore/home_center.html',
                        controller : 'homeCtrl',
                        controllerUrl : 'app/controllers/forstore/buyer_home_ctrl'
                    })).state('buyer_order', angularAMD.route({
                        url: '/order',
                        templateUrl: 'static/view/usercenter/forstore/buyer_order.html',
                        controller: 'orderCtrl',
                        controllerUrl: 'app/controllers/forstore/buyer_order_ctrl'
                    }))
                }
    
        (5)ui-sref
    
            a.绑定在<a>tag,用于‘状态’转换,类似<a>的href属性。底层通过$state.href()来返回编译好的状态填充
    
            b.ui-sref=’stateName’
    
            c.示例:    <a href="#" ui-sref="buyer_order">订单中心</a></li>   (ui-sref的值必须为state的名称)
    
        (6)$stateParams获取url上参数
    
    5.angularAMD (实现按需加载)
    1) angularAMD用来动态加载js文件和js模块,依赖于angular   
    
    2) 简单示例:
    
        (1)引入        <script src="lib/angular/angularAMD.js"></script>
    
        (2)app.js中   
    
                define([ 'angularAMD', 'ui.router',ngLocal], function(angularAMD) {
                    var app = angular.module('myApp', [ 'ui.router', 'ui.bootstrap', 'ng.local']);
                    app.init = function() {
                        angularAMD.bootstrap(app);
                    };
                })
    
        (3)app.config中的 route变成 angularAMD.route({ })
    

    十、$resource

    1.基本常识
    1)我们并不是直接通过$resource服务本身同服务器通信,$resource是一个创建资源对象的工厂,用来创建同服务端交互的对象
    
    2)ngResource模块是一个可选的angularjs模块,需要引入    <script type="text/javascript" src="/javascripts/angular-resource.js">
    
    3)默认有五种方法
    
        (1)get:      {method:'GET'}            get(params,successFn,errrorFn)
    
        (2)save:     {method:'POST'}           save(params, payload, successFn, errorFn)    代表请求发送的数据体User.save({ },{name:'Ari'},successFn, errorFn)   
    
        (3)query     {method:'GET', isArray:true}    query向指定URL发送一个GET请求,并期望返回一个JSON格式的资源对象集合
                                query()和get()方法之间唯一的区别是AngularJS期望query()方法返回数组
    
        (4)remove    {method:'DELETE'}          remove(params, payload, successFn, errorFn)
    
        (5)delete    {method:'DELETE'} }       delete(params, payload, successFn, errorFn)
    
    2.简单示例
    1)    var app = angular.module('helloApp, ['ngResource']);
    
    2)    var User=$resource('/api/users/:userId',{userId:'@id'});    // 可以把User对象理解成同RESTful的后端服务进行交互的接口
    
    3)     User.get(function(resp){
                //处理成功
    
           },function(err){
                //处理错误
    
           });
    
    
    3.对resource(resource进行扩展(扩展resource我们需要传入第三个参数,该参数是一个对象)——$resource服务
    1)  服务配置方法:$resource(url,[paramDefaults],[ actions]); 
    
    2) 将$resource服务当做自定义服务的基础
    
        (1)angular.module('testApp', ['ngResource']),factory('UserService',['$resource', function($resource){
    
                return $resource('trade/bill',{ },{
    
                findBills : {
                    url : 'trade/bill/all',
                    method : 'GET'
                },
                save : {
                    url : 'trade/bill/save',
                    method : 'POST'
                }
             });
    
              }]);
    
        (2) UserService.findBills(params, payload, successFn, errorFn)
    

    十、脏检查原理

    1.ng只有在指定事件触发后,才进入 $digest cycle(脏检查循环)
    1)DOM事件,譬如用户输入文本,点击按钮等。( ng-click )
    
    2)XHR响应事件 ( $http )
    
    3)浏览器Location变更事件 ( $location )
    
    4)Timer事件( $timeout , $interval )
    
    5)执行 $digest() 或 $apply()
    

    2.注意

    1) $apply会使ng进入 $digest cycle , 并从$rootScope开始遍历(深度优先)检查数据变更
    
    2)$digest仅会检查该scope和它的子scope,当你确定当前操作仅影响它们时,用$digest可以稍微提升性能
    

    参考网址

    AngularJS基础知识1

    走进AngularJs(六) 服务

    Angular中文社区

    AngularJS官网

    AngularJS 中的Promise — $q服务详解

    AngularJS 脏检查深入分析

    angular性能优化心得

    AngularJS中使用$resource(已更新)

    Angular-Ui-Router

    angularjs执行流程详解

    AngualrJS学习笔记3–AngularJS的工作原理

    注:文章是经过参考其他的文章然后自己整理出来的,有可能是小部分参考,也有可能是大部分参考,但绝对不是直接转载,觉得侵权了我会删,我只是把这个用于自己的笔记,顺便整理下知识的同时,能帮到一部分人。
    ps : 有错误的还望各位大佬指正,小弟不胜感激

    展开全文
  • angularJS

    千次阅读 2019-04-27 17:35:21
    AngularJS的主要特点是 mvc 数据双向绑定 分模块 依赖注入 mvc m: $Scope 变量 V:视图 c:controller=function(){} 控制器 方法 Angularjs的用法 1.在一个有起始标签的元素开始标签内使用 ng-app来指定...
  • 随着Angular版本的频繁推出,有必要了解下AngularJS、 Angular 2、Angular 4 的区别。 字面上的区别 (1)我们常说的 Angular 1 是指 AngularJS; 从Angular 2 开始已经改名了。不再带有JS,只是单纯的 Angular...
  • angularJS路由详解

    千次阅读 2017-09-24 19:57:39
    快乐源于分享
  • 本次讲解的版本是AngularJS-1,最流行的可能还是AngularJS1吧 1.什么是AngularJS AngularJS 诞生于 2009 年,由 Misko Hevery 等人创建,后为 Google 所收购。是一款优秀的前端 JS框架,已经被用于 Google 的多款...
  • angular.copy(深拷贝)基本用法

    千次阅读 2018-04-19 11:42:47
    对于一个对象数组$scope.content = [ {name:1}, {name:20} ]第一种copy方法$scope.content2 = angular.copy($scope.content) console.log($scope.content2);第二种copy方法angular.copy(source, [destination]);...
  • 3.windows下安装angularJS

    2019-08-16 14:43:44
    安装angularJS的前提的是已经安装了node,如果未安装node,可以参考我的另一篇文章 https://mp.csdn.net/postedit/99672681 1.typescript npm install -g typescript 验证安装是否成功:tsc -v 2.angular cli安装...
  • angularJS环境配置篇

    千次阅读 2017-03-01 12:57:42
    angularJS需要依赖node和npm。 Node.js 和 npm 对使用 Angular 和其他平台进行现代网络开发是至关重要的。 Node 驱动客户端开发和构建工具。 npm 包管理器本身是 node 应用,用于安装 JavaScript 库。 在终端/...
  • AngularJS中文入门教程

    万次阅读 2014-01-15 16:09:09
    AngularJS入门教程00:引导程序 4517 angularjs 03-29 14:14 01-07 17:25 15 AngularJSAngularJS 入门教程 AngularJS入门教程01:静态模板2563 angularjs 03-29 14:16 12-30 17:47 4 ...
  • AngularJS开发指南 中文教程

    千次阅读 2014-01-15 16:08:27
    AngularJS开发指南01:AngularJS简介2669 angularjs 03-29 18:12 10-23 18:08 12 AngularJSAngularJS 开发指南 AngularJS开发指南02:引导程序1576 angularjs 03-29 18:13 07-09 16:27 2 ...
  • AngularJS开发指南

    千次阅读 2014-03-04 21:43:37
    AngularJS开发指南01:AngularJS简介2669 angularjs 03-29 18:12 10-23 18:08 12 AngularJSAngularJS 开发指南 AngularJS开发指南02:引导程序1576 angularjs 03-29 18:13 07-09 16:27 2 ...
  • AngularJS 所有版本下载

    万次阅读 2019-04-25 10:01:19
    官网下载:https://angularjs.org/ AngularJS 所有版本:https://code.angularjs.org/ GitHub 上持续更新 AngularJS 的链接:https://github.com/angular/angular.js/releases 翻墙:...
  • 如何在eclipse中安装angularjs插件

    万次阅读 2018-01-04 15:10:32
    如何在eclipse中安装angularjs插件 1,首先,在eclipse中使用angularjs的时候,由于没有相应的提示,导致在开发的时候给我们带来了很多的不便,需要在这上面耗费一些时间。那么这时候我们都在想可不可以让eclipse也...
  • angularjs中使用jquery

    千次阅读 2015-04-15 13:48:27
    Angularjs中使用jquery的话需要使用指令(directive) 指令怎么用请百度,直接讲怎么整合jquery。 例如给一个div绑定一个点击事件,使得它的css样式发生变化 angular.module('myapp',[]) .directive('myclick',...
  • Eclipse上安装angularjs插件

    千次阅读 2016-05-10 10:38:00
    安装地址:http://oss.opensagres.fr/angularjs-eclipse/0.5.0/  全选,下一步,接受,安装。 安装完成之后需要将项目转换为angularjs项目:项目右键,选中configure
  • AngularJs 刷新页面

    万次阅读 2017-01-17 15:51:46
    AngularJs 刷新页面可采用下面的方式:首先先在控制器中注册$window,然后定义函数$scope.reloadRoute,在需要刷新页面的地方调用函数$scope.reloadRoute即可。 $scope.reloadRoute = function () {  $window....
1 2 3 4 5 ... 20
收藏数 63,725
精华内容 25,490
关键字:

angularjs