zoukankan      html  css  js  c++  java
  • AngularJS_简介、特性及基本使用_及其工作原理

    转自:angularJS 的工作原理

    转自:通过<script>标签引入到 HTML 中那么此时 Angular 就做为一个普通的 DOM 节点等待浏览器解析

    当浏览器解析到这个节点时,发现它是一个 js 文件,那么浏览器会停止解析剩余的 DOM 节点,开始执行这个js(即angular.js)

    同时 Angular 会设置一个事件监听器来监听浏览器的 DOMContentLoaded 事件

    当 Angular 监听到 DOMContentLoaded 事件时,就会启动 Angular 应用

    1. 初始化阶段

    Angular 开始启动后,它会查找 ng-app 指令

    然后初始化一系列必要的组件(即 $injector、$compile 服务以及 $rootScope),接着重新开始解析 DOM 树

    2. 编译、链接阶段

    $compile 服务通过遍历 DOM 树的方式查找有声明指令的 DOM 元素

    当碰到带有一个或多个指令的 DOM 元素时,它会排序这些指令(基于指令的priority优先级)

    然后使用 $injector 服务查找 和 收集指令的 compile 函数并执行它

    每个节点的编译方法运行之后,$compile 服务就会调用链接函数。这个链接函数为绑定了封闭作用域的指令设置监控。这一行为会创建实时视图

    最后,在$compile 服务完成后,AngularJS 运行时就准备好了

    3. 运行阶段

    Angular提供了自己的事件循环

    指令自身会注册事件监听器,因此当事件被触发时,指令函数就会运行在 AngularJS 的 $digest 循环中

    $digest 循环会等待 $watch 表达式列表

    当检测到模型变化后,就会调用 $watch 函数,然后再次查看 $watch 列表以确保没有模型被改变

    一旦 $digest 循环稳定下来,并且检测到没有潜在的变化了,执行过程就会离开 Angular 上下文并且通常会回到浏览器中,DOM 将会被渲染到这里

    当你用浏览器去访问 index.html 的时候,angularJS 做了以下事情去渲染页面:

    1. 加载 html,然后解析成 DOM
    2. 加载 angular.js 脚本
    3. AngularJS 等待 DOMContentLoaded 事件的触发
    4. AngularJS 寻找 ng-app 指令,根据这个指令确定应用程序的边界
    5. 使用 ng-app 中指定的模块配置$injector
    6. 使用 $injector 创建 $compile 服务 和 $rootScope 
    7. 使用 $compile 服务编译 DOM 并把它链接到 $rootScope 上
    8. ng-init 指令对 scope 里面的变量 xxx 进行赋值
    9. 对表达式 {{xxx}} 进行替换,于是乎,页面显示数据

    • angular 和浏览器进行交互,粗略来讲分为 3 个阶段:

    1. 浏览器的事件回路一直等待着事件的触发,事件包括用户的交互操作、定时事件或者网络事件(如服务器的响应等)

    2. 一旦有事件触发,就会进入到 Javascript 的 context 中,一般通过回调函数来修改 DOM

    3. 等到回调函数执行完毕之后,浏览器又根据新的 DOM 来渲染新的页面

    • AngularJS 修改了一般的 Javascript 工作流,并且提供了它自己的事件处理机制

    这样就把 Javascript 的 context 分隔成两部分

    一部分是原生的 Javascript 的 context

    另一部分是 AngularJS 的 context

    只有处在 AngularJS 的 context 中的操作才能享受到 Angular 的 data-binding、exception handling、property watching 等服务

    但是对于外来者(如原生的 Javascript 操作、自定义的事件回调、第三方的库等)Angular 也不是一概不接见

    可以使用 AngularJS 提供的 $apply() 函数,将这些外来者包进 AngularJS 的 context 中,让 Angular 感知到他们产生的变化

    1. 首先,浏览器会一直处于监听状态,一旦有事件被触发,就会被加到一个 event queue 中,event queue 中的事件会一个一个的执行

    2. event queue 中的事件如果是被 $apply() 包起来的话,就会进入到 AngularJS 的 context 中,这里的 fn() 是我们希望在 AngularJS 的 context 中执行的函数

    3. AngularJS 将执行 fn() 函数,通常情况下,这个函数会改变应用的某些状态

    4. 然后 AngularJS 会进入到由两个小循环组成的 $digest 循环中

    一个循环是用来处理 $evalAsync 队列的

    用来 schedule 一些需要在渲染视图之前处理的操作,通常通过 setTimeout(0) 实现

    速度会比较慢,可能会出现视图抖动的问题

    一个循环是处理 $watch 列表的

    是一些表达式的集合,一旦有改变发生,那么 $watch 函数就会被调用

    $digest 循环会一直迭代知道 $evalAsync 队列为空并且 $watch 列表也为空的时候,即 model 不再有任何变化。

    5. 一旦 AngularJS 的 $digest 循环结束,整个执行就会离开 AngularJS 和 Javascrip 的 context,紧接着浏览器就会把数据改变后的视图重新渲染出来

    这段代码有了一个 input 来接收用户的输入

    在用浏览器去访问这个 html 文件的时候,input上的 ng-model 指令会给 input 绑上keydown事件

    并且会给 name 变量建立一个 $watch 来接收变量值改变的通知。

    在交互阶段主要会发生以下一系列事件:

    1. 当用户按下键盘上的某一个键的时候(比如说A),触发 input 上的 keydown 事件

    2. input 上的指令察觉到 input 里值的变化,调用 $apply(“name=‘A'”) 更新处于 AngularJS 的 context 中的 model

    3. AngularJS 将'A'赋值给 name

    4. $digest 循环开始,$watch 列表检测到 name 值的变化,然后通知 {{name}} 表达式,更新 DOM

    5. 退出 AngularJS 的 context,然后退出 Javascript 的 context 中的 keydown 事件

    6. 浏览器重新渲染视图

    AngularJS

    Google 推出的开源的前端 JS 结构化框架,主体是 页面中的动态数据与内存的读取

    相较于 jQuery

    jQuery 是前端函数库,封装简化 DOM 操作

    应用

    构建单页面 SPA Web 应用____Single Page Application

    将所有的活动局限于一个 html 页面 (即使页面跳转了,也是在本页面跳转)

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

    利用的就是 ajax 技术,路由

    Web App 应用

    饿了么微信网页版

    后台管理应用: 阿里云、土豆后台、唯品会... ...

    特性:

    双向数据绑定

    声明式依赖注入

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

    完善的页面指令

    定制表单验证

    Ajax 封装

    老版本 angular-1.2.xx

     

    新版本 angular-1.5.xx

     

    输入框的内容,实时显示到下方:

    • $(function(){
          $('input').keyup(function(){    // 不能使用 change,在失去焦点时触发
              $('span').html(this.value);
          });
      });
      
      /*************** angular-1.2***************/

    <body ng-app>    是 <body ng-app=""> 的简写____指向创建模块的名字

    angularJS 不必写一行 js 代码,即可实现,且速度更快

    使用:(ng 是核心模块,其他都是功能扩展模块)

    1. 引入 angular.js

    <script src='./js/angular-1.2.29/angular.js'></script>

    2. ng-app 指令,通常 <body ng-app>____使用 插件 ng-inspector 进行数据查看

    告诉 angular 核心,管理 当前标签 所包含的整个区域

    并且自动创建 $rootScope 根作用域对象

    3. 在管理的标签区域内使用 angularJS

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

    {{表达式}}    显示数据,从 当前作用域对象 $rootScope 的指定属性名上取

    通常有一个返回值,可以放到任何需要的位置,

    剖析: 

    数据流向

    页面上初始化时无数据____ng-model 是双向数据绑定

    首先是从页面流向内存,再从内存流向页面的 angular 表达式 和 angular 指令

    ② 页面上初始化时有数据____ng-init="username='SunWuKong'"

    ng-init 是单向数据绑定,从页面 view 流向 model 内存

    {{表达式}} 也是单向数据绑定,从内存 model 流向 view 页面

    下载: ng-inspector 插件打开的就是 angularJS 的 内存____最大的对象就是 $rootScope 

    数据绑定:

    数据从一个地方 A 移动(传递)到另一个地方 B____这个过程由框架去完成

    双向数据绑定(视图 view <----> model 模型)---- (网页 <----> 内存)____页面主要就是 angular 指令 和 angular 表达式

    数据可以从 view 流向 model,也可以从 model 流向 view

    使用 ng-model 使得 页面 的数据存储到 内存

    单向数据绑定

    View-->Model  : ng-init

    Model-->View  : {{表达式}} 去内存中获取数据,渲染到页面

    依赖注入

    依赖对象: 完成某个特定功能必须要某个对象才能实现____比如 定义子对象,必须形参 $scope

    依赖注入: 依赖对象 以形参的形式 被注入进来使用____声明式依赖注入 (对应的一个叫 命令式依赖注入'遍历指定数组每个元素')

    命令式 更注重过程 (解答题)

    声明式 更注重结果,是对命令式的局部包装 (选择题)

    又由于代码压缩,会改变 形参 的命名,所以必须使用 ["形参", function(形参){...}] 显示声明依赖注入

    MVC 模式

    M: Model, 即模型, 储存数据的容器, 提供操作数据的方法

    在 angular 中为 scope

    V: View, 即视图, 显示 Model 的数据, 将数据同步到 Model, 与用户交互

    在 angular 中为 页面,包括: html/css/directive/expression

    C: Controller, 即控制器, 初始化 Model 数据, 为 Model 添加行为方法

    在 angular 中为 angular 的 ng-controller

    MVVM 模式

    在 MVVM 中 angular 的 controller 不再是架构的核心

    angular 的 controller 只是起辅助作用,用来辅助 $scope 对象,即 VM 层

    M: Model, 即数据模型

    在 angular 中为 scope 中的各个数据对象

    V: View, 即视图

    在 angular 中为 页面

    VM: ViewModel, 即视图模型

    在 angular 中为 scope 对象

    根作用域对象

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

    作用域对象

    根作用域对象的 属性和方法 与页面中的 指令/表达式 是关联的

    控制器对象

    用于控制 angularJS 应用数据的 实例对象

    ng-controller 指定控制器构造函数____形参必须是 $scope____依赖注入

    angular 会自动 new 这个构造函数创建控制器对象

    同时 还会创建一个新的作用域对象 $scope ,  它是 $rootScope 的 (继承关系)子对象____$scope____作用域对象

    (不可能用 ng-init 初始化所有对象)

    • API: ng/function/angular.module()____一个参数是获取,多个参数是创建

    可以在全局位置创建、注册、获取 Angular 模块

    所有模块都必须使用这个机制注册 才能在应用中生效

    使用:

    1. 创建模块对象        <body ng-app="myApp">____ng-app 指向创建模块的名字

    var myModule = angular.module("myApp", []);

    2. 生成作用域对象____取代 自定义构造函数

    myModule.controller("myController1", function($scope){

    $scope.empName = "SunWuKong";

    });

    myModule.controller("myController2", function($scope){

    $scope.empName = "ZhuBaJie";

    });

    --------------------- 优化 ----------------------链式调用 (返回值为 作用域对象)

    angular.module("myApp", []).controller("myController1", function($scope){

    $scope.empName = "SunWuKong";

    }).controller("myController2", function($scope){    // 隐式声明依赖注入

    $scope.empName = "ZhuBaJie";

    });

    注意:

    js 代码压缩时,会改变形参,导致 angular 无法解析

    解决: 显示声明依赖注入

    angular.module("myApp", []).controller("myController1", ['$scope', function($scope){

    $scope.empName = "SunWuKong";

    }]).controller("myController2", ['$scope', function($scope){

    $scope.empName = "ZhuBaJie";

    }]);

    • {{表达式}}

    单项数据绑定

    如果是变量 会在作用域链中寻找变量 {{abc.split("").reverse().join("")}}____ 字符串反转

    还可以是 {{123}}{{'abc'}}{{true}}

    {{null}}、{{undefine}}、{{NaN}}、{{Infinity}} 会被解析成 空串 "",不显示任何内容 

    • 项目

    一个项目下来,首先是 UI 设计页面效果  

    UI 从 14 年开始火,比 美工 高一个档次  

    然后前端工程师分析 UI 设计图,进行静态 html 页面设计 

    接下来是,数据的动态展现,与后端交互

    然后是用户的交互,数据的展现

    angularJS 开发第一步就是 新建 ng-app="myApp"

    ng-controller 实现子作用域对象 $scope

    ng-model 实现双向数据绑定

    {{表达式}} 从内存显示数据到页面

    • 常用指令
    • 点击事件

    <button ng-click="getTotalPrice()">计算</button>

    • 遍历数组显示数据____数据有几个数组就会产生几个新的作用域

    <div>

    <h2>人员信息列表</h2>

    <ul>

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

    {{$index}} ---- {{person.username}} ---- {{person.age}}

    {{$first}} ---- 第一个 返回 true

    {{$last}} ---- 最后一个 返回 true

    {{$odd}} ---- 奇数返回 true,从 1 开始计算

    {{$even}} ---- 偶数返回 true,从 1 开始

    </li>

    </ul>

    </div>

     

    • ng-bind 指令 解决数据闪屏:由于用户网速不好,第一次打开页面会看到 {{表达式}}

    浏览器引擎从上往下解析

    因为浏览器还没有解析到引入的 angular.js,所以页面还没有生效,导致了 数据闪屏

    <div>

    <p>{{123}}</p>

    优化为:

    <p ng-bind="123"></p>

    </div>

    • ng-show 布尔类型,如果为 true 则 显示
    • ng-hide 布尔类型,如果为 true 则 隐藏

    <div>

    <button ng-click="switchLike()">切换喜欢</button>

    <p ng-show="isLike">我喜欢刘亦菲</p>

    <p ng-hide="isLike">刘亦菲喜欢我</p>

    </div>

    ------------------- javascript ------------------

    $scope.isLike = true;

    $scope.switchLike = function(){

    $scope.isLike  = !$scope.isLike ;

    };

    ---------------------------------------- 控制 css 杨样式 --------------------------------------------------

    • ng-style  动态引用 js 指定的的样式对象 {"color":"blue", "backgrouond": "red"};

    • ng-mouseenter
    • ng-mouseleave

    • ng-class 动态引用定义的样式    {"aClass": true, bClass: true};

     

    字数统计,实时显示

    • <html>
          <head>
              <meta charset="UTF-8">
              <style type="text/css">
                  textarea {
                      resize: none;
                  }
              </style>
          </head>
          <body ng-app="myApp">
              <div ng-controller="MyCtrl" >
                  <h2>个性签名:</h2>
                  <textarea cols="30" rows="10" ng-model="words"></textarea>
                  <div>
                      <button ng-click="saveWords()">保存</button>
                      <button ng-click="readWords()">读取</button>
                      <button ng-click="clearWords()">删除</button>
                  </div>
                  <p>剩余字数: <span ng-bind="getCount()"></span></p>
              </div>
              
              <script type="text/javascript" src="https://cdn.bootcss.com/angular.js/1.5.10/angular.js"></script>
              <script type="text/javascript">
                  var limitLength = 100;    // 字数限制 100 字
                  //window.onDOMContentLoaded = function(){    // 会报错 ---- 看上面的工作原理
                      angular.module("myApp", []).controller("MyCtrl", ["$scope", function($scope){
                     $scope.words = "哈哈";
                          
                     $scope.getCount = function(){
                          $scope.wordsLength = limitLength - $scope.words.length;
                              
                          if($scope.words.length > 100){    // 超出字数限制,让用户输入失效
                               $scope.words = $scope.words.slice(0, limitLength);
                          };
                              
                          return $scope.wordsLength;
                      };
                          
                      $scope.saveWords = function(){
                          sessionStorage.setItem("session_key", JSON.stringify($scope.words));
                          console.log("已经保存到 sessionStorage ");
                      };
                          
                      $scope.readWords = function(){
                          $scope.words = JSON.parse(sessionStorage.getItem("session_key")) || "";    // 如果读不到,则返回 null
                          console.log("已经读取 sessionStorage ");
                      };
                          
                      $scope.clearWords = function(){
                          sessionStorage.removeItem("session_key");
                          $scope.words = "";
                      };
                   }]);
               //};
              </script>
          </body>
      </html>

    数据的动态展示

    • <html>
          <head>
              <meta charset="UTF-8">
              <style type="text/css">
                  textarea {
                      resize: none;
                  }
              </style>
          </head>
          <body ng-app="myApp">
              <div ng-controller="MyCtrl" >
                  <h2>Hero  </h2>
                  
                  <div>
                      <input type="text" ng-model="heroName"/>
                      <button ng-click="addHero()">添加</button>
                  </div>
                  
                  <div ng-repeat="each in heros">
                      <input type="checkbox" ng-model="each.isChecked" /><span ng-bind="each.name"></span>
                  </div>
                  
                  <button ng-click="removeHreo()">删除所选对象</button>
              </div>
              
              <script type="text/javascript" src="https://cdn.bootcss.com/angular.js/1.5.10/angular.js"></script>
              <script type="text/javascript">
                  // window.onDOMContentLoaded = function(){    // 会报错 ---- 看上面的工作原理
                      angular.module("myApp", []).controller("MyCtrl", ["$scope", function($scope){
                      $scope.heros = [
                          {"name": "Groot", "isChecked": false},
                          {"name": "玩锤子的", "isChecked": false},
                          {"name": "浩克", "isChecked": false},
                          {"name": "洛基", "isChecked": false}
                      ];
                          
                      $scope.addHero = function(){
                          var isExit = false;
                          $scope.heros.forEach(function(each, index){
                              if(each.name === $scope.heroName){
                                  isExit = true;
                                  $scope.heroName = "";
                              };
                          });
                              
                          if($scope.heroName && !isExit){
                              $scope.heros.unshift({"name": $scope.heroName, "isChecked": false});
                              $scope.heroName = "";
                          };
                      };
                      /****  // 方式1 ---- 删除 数组中不符合条件的元素
                      $scope.removeHreo = function(){
                           $scope.heros.forEach(function(each, index){
                               if(each.isChecked){
                                   $scope.heros.splice(index, 1);    // 从 index 开始删,删 1 个
                                   $scope.removeHreo();
                               };
                           });
                      };
                      ****/
                             // 方式2 ---- 保留 数组中符合条件的元素
                             $scope.removeHreo = function(){
                           var tempArr = $scope.heros;
                           $scope.heros = [];
                           tempArr.forEach(function(each, index){
                               if(!each.isChecked){
                                   $scope.heros.push(each);
                               };
                           });
                       };
                   }]);
               // };
              </script>
          </body>
      </html>

     

    --------小尾巴 ________一个人欣赏-最后一朵颜色的消逝-忠诚于我的是·一颗叫做野的心.决不受人奴役.怒火中生的那一刻·终将结束...
  • 相关阅读:
    FJUT3260
    Codeforces Round #387 (Div. 2)
    poj 1375
    试题 历届试题 蚂蚁感冒(模拟)
    丢手绢(尺取)
    「金」点石成金(dfs)
    小A买彩票(dp)
    不平行的直线
    最少交换次数
    第k小数(桶排序)
  • 原文地址:https://www.cnblogs.com/tianxiaxuange/p/10223134.html
Copyright © 2011-2022 走看看