您的位置:68399皇家赌场 > 服务器租用 > www.68399.com:AngularJS 双向数据绑定详解简单实例

www.68399.com:AngularJS 双向数据绑定详解简单实例

发布时间:2019-06-29 00:32编辑:服务器租用浏览(132)

    上个例子,大家看了数码变化后,视图也会活动生成。那么这么些例子则是扭曲,视图变化,导致数据也随着变化,那么数量变动后,大家怎么精晓吗,那儿我们能够通过其余三个因素将数据再显示出来。

    1、手动绑定

    function User( uid ) {
     var binder = new DataBinder( uid ),
    
       user = {
        attributes: {},
    
        // The attribute setter publish changes using the DataBinder PubSub
        set: function( attr_name, val ) {
         this.attributes[ attr_name ] = val;
         binder.trigger( uid   ":change", [ attr_name, val, this ] );
        },
    
        get: function( attr_name ) {
         return this.attributes[ attr_name ];
        },
    
        _binder: binder
       };
    
     // Subscribe to the PubSub
     binder.on( uid   ":change", function( evt, attr_name, new_val, initiator ) {
      if ( initiator !== user ) {
       user.set( attr_name, new_val );
      }
     });
    
     return user;
    }
    

    下面的demo演示:

    双向绑定是AngularJS最实用的效率,它节省了汪洋的代码,使大家注意于数据和视图,不用浪费大批量的代码在Dom监听、数据同步上,关于双向更新,可看下图:www.68399.com 1

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>data-binding-drity-check</title>
    </head>
    
    <body>
      <input q-event="value" ng-bind="value" type="text" id="input">
      <div q-event="text" ng-bind="value" id="el"></div>
      <script>
    
      var elems = [document.getElementById('el'), document.getElementById('input')];
    
      var data = {
        value: 'hello!'
      };
    
      var command = {
        text: function(str) {
          this.innerHTML = str;
        },
        value: function(str) {
          this.setAttribute('value', str);
        }
      };
    
      var scan = function(elems) {
        /**
         * 扫描带指令的节点属性
         */
        for (var i = 0, len = elems.length; i < len; i  ) {
          var elem = elems[i];
          elem.command = {};
          for (var j = 0, len1 = elem.attributes.length; j < len1; j  ) {
            var attr = elem.attributes[j];
            if (attr.nodeName.indexOf('q-event') >= 0) {
              /**
               * 调用属性指令
               */
              var dataKey = elem.getAttribute('ng-bind') || undefined;
              /**
               * 进行数据初始化
               */
              command[attr.nodeValue].call(elem, data[dataKey]);
              elem.command[attr.nodeValue] = data[dataKey];
            }
          }
        }
      }
    
      /**
       * 脏循环检测
       * @param {[type]} elems [description]
       * @return {[type]}    [description]
       */
      var digest = function(elems) {
        /**
         * 扫描带指令的节点属性
         */
        for (var i = 0, len = elems.length; i < len; i  ) {
          var elem = elems[i];
          for (var j = 0, len1 = elem.attributes.length; j < len1; j  ) {
            var attr = elem.attributes[j];
            if (attr.nodeName.indexOf('q-event') >= 0) {
              /**
               * 调用属性指令
               */
              var dataKey = elem.getAttribute('ng-bind') || undefined;
    
              /**
               * 进行脏数据检测,如果数据改变,则重新执行指令,否则跳过
               */
              if(elem.command[attr.nodeValue] !== data[dataKey]){
    
                command[attr.nodeValue].call(elem, data[dataKey]);
                elem.command[attr.nodeValue] = data[dataKey];
              }
            }
          }
        }
      }
    
      /**
       * 初始化数据
       */
      scan(elems);
    
      /**
       * 可以理解为做数据劫持监听
       */
      function $digest(value){
        var list = document.querySelectorAll('[ng-bind='  value   ']');
        digest(list);
      }
    
      /**
       * 输入框数据绑定监听
       */
      if(document.addEventListener){
        elems[1].addEventListener('keyup', function(e) {
          data.value = e.target.value;
          $digest(e.target.getAttribute('ng-bind'));
        }, false);
      }else{
        elems[1].attachEvent('onkeyup', function(e) {
          data.value = e.target.value;
          $digest(e.target.getAttribute('ng-bind'));
        }, false);
      }
    
      setTimeout(function() {
        data.value = 'fuck';
        /**
         * 这里问啥还要执行$digest这里关键的是需要手动调用$digest方法来启动脏检测
         */
        $digest('value');
      }, 2000)
    
      </script>
    </body>
    </html>
    

    ③$digest循环
    还记得本人前边提到的扩大的风浪循环呢?当浏览器接收到能够被angular context管理的事件时,digest循环就可以接触。那个轮回是由八个更加小的巡回组合起来的。二个管理evalAsync队列,另一个拍卖watch队列。 那个是管理什么的吧?digest将会遍历大家的watch,然后询问它是或不是有总体性和值的成形,直$watch队列都检查过。

    www.68399.com 2

    双向绑定

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>data-binding-hijacking</title>
    </head>
    
    <body>
      <input q-value="value" type="text" id="input">
      <div q-text="value" id="el"></div>
      <script>
    
    
      var elems = [document.getElementById('el'), document.getElementById('input')];
    
      var data = {
        value: 'hello!'
      };
    
      var command = {
        text: function(str) {
          this.innerHTML = str;
        },
        value: function(str) {
          this.setAttribute('value', str);
        }
      };
    
      var scan = function() {
        /**
         * 扫描带指令的节点属性
         */
        for (var i = 0, len = elems.length; i < len; i  ) {
          var elem = elems[i];
          elem.command = [];
          for (var j = 0, len1 = elem.attributes.length; j < len1; j  ) {
            var attr = elem.attributes[j];
            if (attr.nodeName.indexOf('q-') >= 0) {
              /**
               * 调用属性指令
               */
              command[attr.nodeName.slice(2)].call(elem, data[attr.nodeValue]);
              elem.command.push(attr.nodeName.slice(2));
    
            }
          }
        }
      }
    
      var bValue;
      /**
       * 定义属性设置劫持
       */
      var defineGetAndSet = function(obj, propName) {
        try {
          Object.defineProperty(obj, propName, {
    
            get: function() {
              return bValue;
            },
            set: function(newValue) {
              bValue = newValue;
              scan();
            },
    
            enumerable: true,
            configurable: true
          });
        } catch (error) {
          console.log("browser not supported.");
        }
      }
      /**
       * 初始化数据
       */
      scan();
    
      /**
       * 可以理解为做数据劫持监听
       */
      defineGetAndSet(data, 'value');
    
      /**
       * 数据绑定监听
       */
      if(document.addEventListener){
        elems[1].addEventListener('keyup', function(e) {
          data.value = e.target.value;
        }, false);
      }else{
        elems[1].attachEvent('onkeyup', function(e) {
          data.value = e.target.value;
        }, false);
      }
    
      setTimeout(function() {
        data.value = 'fuck';
      }, 2000)
      </script>
    </body>
    
    </html>
    

    模板(app/index.html)

    1. ng-model指令的法力:建构数据模型,在模型中对应当三个变量username用来存放input成分的value;

    在digest流程里面, 会从rootscope开首遍历, 检查有着的watcher。

    4、小结

    为了落到实处这一块成效,大家首先来定义叁个测验文件并预感你能够应用watch来注册三个监视器,并且当有人调用了digest的时候监视器的监听函数会被调用。

    1. {{username}}是三个表明式,angular会自动测算该表明式,替换来相应的值。

    点击按键之后,div内容变成 李四,效果如图:
    www.68399.com 3

    前者数据的双向绑定方法

    function PhoneListCtrl($scope) {
     $scope.phones = [
      {"name": "Nexus S",
       "snippet": "Fast just got faster with Nexus S.",
       "age": 0},
      {"name": "Motorola XOOM™ with Wi-Fi",
       "snippet": "The Next, Next Generation tablet.",
       "age": 1},
      {"name": "MOTOROLA XOOM™",
       "snippet": "The Next, Next Generation tablet.",
       "age": 2}
     ];
    
     $scope.orderProp = 'age';
    }
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>hello, AngularJS!</title>
      <script src="angular.js"></script>
    </head>
    <body>
      <div ng-app>
        <!-- ng-model指令将表单的value绑定到model的username变量-->
        <input ng-model="username" type="text" placeholder="请输入...">
        <p>Hello, <strong>{{username}}</strong>!</p>
      </div>
    </body>
    </html>
    

    福寿齐天机制

    3、前端数据勒迫(Hijacking)

    test/scope_spec.js 
    -------
    /* jshint globalstrict: true */  
    /* global Scope: false */
    'use strict';
    describe("Scope", function() {
    it("can be constructed and used as an object", function() { 
    var scope = new Scope();
    scope.aProperty = 1;
      expect(scope.aProperty).toBe(1);
     });
    });
    

    感激阅读,希望能支援到大家,多谢大家对本站的支撑!

    angular对常用的dom事件,xhr事件等做了包装, 在里面触发进入angular的digest流程。

    其三种办法规是avalon等框架使用的数额胁迫格局。基本思路是运用Object.defineProperty对数据对象做属性get和set的监听,当有数量读取和赋值操作时则调用节点的一声令下,那样使用最通用的=等号赋值就能够了。具体落到实处如下:

    ②蹲点指标属性:watch和digest
    watch和digest是同一个硬币的两面。它们二者同一时间变成了$digest循环的着力:对数码的变迁做出反应。

    3. 手动输入文字,input成分的value发生变化,自动同步到model的usename变量,{{username}}是从模型中读username的值,由此上边strong成分的源委跟着变了。

    你恐怕感兴趣的稿子:

    • javascript贯彻多少双向绑定的三种方式小结
    • AngularJS 双向数据绑定详解轻易实例
    • JS原生数据双向绑定实当代码
    • Angular JS数据的双向绑定详解及实例
    • JavaScript中双向数据绑定详解
    • jQuery完毕html双向绑定作用示例
    • js最简易的双向绑定实例疏解

    先是这里的例子只是轻巧的完结,读者能够深深感受三种办法的异同点,复杂的框架也是透过那样的基本思路滚雪球滚大的。

    • 我们需求三个UI成分和属性相互绑定的艺术
    • 我们供给监视属性和UI成分的改动
    • 咱俩必要让具有绑定的指标和因素都能感知到变化

    案例详解:

    <!DOCTYPE html>
    
    <html ng-app="App">
    <head>
      <script type="text/javascript" src="http://sandbox.runjs.cn/uploads/rs/394/xjz9g1bv/angular.js"></script>
      <script type="text/javascript">
    
      var App = angular.module("App", []);
    
      App.controller("ctrl", function ($scope) {
    
           $scope.username='张三'
        });
    
      </script>
    </head>
      <body>
        <div ng-controller ="ctrl">
          <input type='text' ng-model='username' />
    
          <div>{{username}}</div>
        </div>
      </body>
    </html>
    

    2、脏检查体制

    地点代码中的$$前缀在AngularJS框架中被认为是私有变量,它们不应当在运用的外表被调用。
    今昔我们得以来定义watch函数了。它接受多个函数作为参数,并且将它们积攒在$watchers数组中。大家想要每一种Scope对象都存有那么些函数,由此大家将它加多到Scope的原型中:

    一道数据是angular帮大家做到的。

    <!DOCTYPE html>
    
    <html ng-app="App">
    <head>
      <script type="text/javascript" src="http://sandbox.runjs.cn/uploads/rs/394/xjz9g1bv/angular.js"></script>
      <script type="text/javascript">
    
      var App = angular.module("App", []);
    
      App.controller("ctrl", function ($scope) {
    
           $scope.username='张三'
    
            $scope.changename=function(){
              $scope.username='李四';  
            }
        });
    
      </script>
    </head>
      <body>
        <div ng-controller ="ctrl">
          <button class='btn btn-primary' ng-click='changename();'>
            username='李四'
          </button>
          <!--页面加载初期,用户可能会看到绑定的表达式-->
          <div>{{username}}</div>
          <!--此绑定不会出现上述情况-->
          <div ng-bind='username'></div>
        </div>
      </body>
    </html>
    

    但值得注意的是defineProperty支持IE8以上的浏览器,这里可以选取__defineGetter__ 和 __defineSetter__ 来做协作不过浏览器包容性的由来,直接用defineProperty就可以了。至于IE8浏览器仍供给运用其余方法来做hack。如下代码能够对IE8进行hack,defineProperty匡助IE8。比方利用es5-shim.js就足以了。(IE8以下浏览器忽略)

    例如:controllers.js

    angular的双向数据绑定,个人驾驭是,通过model建设构造数据模型,那么视图上的多少就能对应存款和储蓄在angular程序里,视图上的多寡变化会同步到model,model的多寡变动也会同步到视图。

    这边大家只演示有了数额以往,怎么样绑定到视图上。

    您恐怕感兴趣的作品:

    • AngularJS学习笔记(三)数据双向绑定的大致实例
    • AngularJS 双向数据绑定详解轻松实例
    • JS原生数据双向绑定完结代码
    • Angular JS数据的双向绑定详解及实例
    • JavaScript中双向数据绑定详解
    • jQuery达成html双向绑定功效示例
    • js最简易的双向绑定实例疏解

    下一场,在filter过滤器前面加多贰个orderBy过滤器用其来管理进入迭代器的数目。orderBy过滤器以二个数组作为输入,复制一份别本,然后把别本重排序再出口到迭代器。
    AngularJS在select成分和orderProp模型之间创设了贰个双向绑定。而后,orderProp会被用作orderBy过滤器的输入。

    您或者感兴趣的稿子:

    • javascript兑现多少双向绑定的两种艺术小结
    • AngularJS学习笔记(三)数据双向绑定的简易实例
    • JS原生数据双向绑定实今世码
    • Angular JS数据的双向绑定详解及实例
    • JavaScript中双向数据绑定详解
    • jQuery实现html双向绑定效用示例
    • js最简易的双向绑定实例解说

    翻开效果:
    www.68399.com 4

    上述就是本文的全体内容,希望对大家的求学抱有援助,也冀望我们多多支持脚本之家。

    先是,大家新建名称叫$$digestOnce,并且调动它以便它能够在富有监视器上运维一回,然后回到三个布尔值来证实有未有此外变化:
    src/scope.js

    运维结果:程序运维后,在输入框输入文字,下边会与输入框内容同步变化。是或不是很诧异!从前必要写一大段js代码的专门的学问(监听onchange事件,将input的value赋给上面包车型大巴strong成分),未来只用一个ng-model指令就成功了。Perferct!

    www.68399.com,视图—>数据

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>data-binding-method-set</title>
    </head>
    <body>
      <input q-value="value" type="text" id="input">
      <div q-text="value" id="el"></div>
      <script>
        var elems = [document.getElementById('el'), document.getElementById('input')];
    
        var data = {
          value: 'hello!'
        };
    
        var command = {
          text: function(str){
            this.innerHTML = str;
          },
          value: function(str){
            this.setAttribute('value', str);
          }
        };
    
        var scan = function(){    
          /**
           * 扫描带指令的节点属性
           */
          for(var i = 0, len = elems.length; i < len; i  ){
            var elem = elems[i];
            elem.command = [];
            for(var j = 0, len1 = elem.attributes.length; j < len1; j  ){
              var attr = elem.attributes[j];
              if(attr.nodeName.indexOf('q-') >= 0){
                /**
                 * 调用属性指令,这里可以使用数据改变检测
                 */
                command[attr.nodeName.slice(2)].call(elem, data[attr.nodeValue]);
                elem.command.push(attr.nodeName.slice(2));
              }
            }
          }
        }
    
        /**
         * 设置数据后扫描
         */
        function mvSet(key, value){
          data[key] = value;
          scan();
        }
        /**
         * 数据绑定监听
         */
        elems[1].addEventListener('keyup', function(e){
          mvSet('value', e.target.value);
        }, false);
    
        scan();
    
        /**
         * 改变数据更新视图
         */
        setTimeout(function(){
          mvSet('value', 'fuck');
        },1000)
    
      </script>
    </body>
    </html>
    

    随后,大家重定义digest以便它亦可运营“外循环”,在退换产生时调用$digestOnce:

    数据-->视图

    前端的视图层和数据层有的时候供给贯彻双向绑定(two-way-binding),举例mvvm框架,数据驱动视图,视图状态机等,研讨了多少个最近主流的数量双向绑定框架,计算了下。方今兑现数据双向绑定重要有以下二种。

    3.发表者-订阅者形式(PubSub格局) 统一策画该形式背后的严重性引力是推进形成松散耦合。在这种情势中,并不是一个对象调用另三个指标的秘诀,而是叁个指标订阅另二个对象的特定活动并在气象改造后获得通报。订阅者也称之为观看者,而补观望的靶子称为发表者或主旨。当发生了一个第一的事件时,发表者将会通报(调用)全数订阅者并且大概时时以事件指标的款型传递信息。

    以优良的mvvm框架angularjs为代表,angular通过检查脏数据来进展UI层的操作更新。关于angular的脏检查测验,有几点需求了然些:

    paper也提供了unsubscribe()方法,该办法表示从订阅者数组(即subscribers属性)中除去订阅者。paper最终二个入眼的主意是publish(),它会调用这么些订阅者的秘技,简单来讲,发表者对象paper须求持有以下这一个成员:

    正如老的落到实处况势,有一些像旁观者编制程序格局,首要思路是经过在数量对象上定义get和set方法(当然还也有此外方式),调用时手动调用get或set数据,退换多少后出发UI层的渲染操作;以视图驱动数据变化的光景主要采用与input、select、textarea等因素,当UI层变化时,通过监听dom的change,keypress,keyup等事件来出发事件改造数据层的数额。整个进度均通过函数调用完结。

    以此测量检验用来创造一个Scope,并在它下边赋二个大肆值。大家得以轻易的让那么些测量试验通过:创设src/scope.js文件然后在里面增加以下内容:
    src/scope.js 

    • 脏检查实验机制并不是利用按时检查实验。 - 脏检查实验的时机是在数码爆发变化时开始展览。
    • angular对常用的dom事件,xhr事件等做了打包, 在里头触发进入angular的digest流程。 - 在digest流程里面, 会从rootscope发轫遍历, 检查有着的watcher。 (关于angular的具体安插能够看别的文书档案,这里只谈谈数量绑定),那我们看下脏检查评定该怎么去做:首若是透过安装的数目来需找与该数据有关的兼具因素,然后再相比较数据变化,假使生成则开始展览指令操作

    www.68399.com 5

    持有那二种情势都须要二个type参数,因为公布者可能接触多个事件(譬如同不时间发表一本笔记和一份报纸)而用户也许仅选用订阅当中一种,而不是别的一种。

    ----
    
    Scope.prototype.$$digestOnce = function(){
      var length = this.$$watchers.length;
      var watcher, newValue, oldValue, dirty;
      while(length--){
        watcher = this.$$watchers[length];
        newValue = watcher.watchFn(this);
        oldValue= watcher.last;
        if(newValue !== oldValue){
          watcher.last == newValue;
          watcher.listenerFn(newValue, oldValue, this);
          dirty = true;
        }
      }
       return dirty;
    };
    

    本文由68399皇家赌场发布于服务器租用,转载请注明出处:www.68399.com:AngularJS 双向数据绑定详解简单实例

    关键词: 68399皇家赌场

上一篇:bootstrap fileinput完整实例共享

下一篇:没有了