zoukankan      html  css  js  c++  java
  • 使用Object.observe 实现数据绑定

    Object.observe API概述

    最近,JavaScript的MVC框架在Web开发届非常盛行。在实现MVC框架的时候,一个非常重要的技术就是数据绑定技术。如果要实现模型与视图的分离,就必须要使用数据绑定技术。但是,MVC框架的原作者对于数据绑定处理实现得并不如人意,因此,Google公司在ECMAScript中封装了一个Object.observe API,专用于实现数据绑定处理(目前将其正式使用在V8中)。

    Object.observe API可以被称为一种“可以对任何对象的属性值修改进行监视的事件处理函数”。

    在Firefox浏览器中,实现了与之相类似的可以对DOM对象进行观察的Mutation观察器

    目前为止,Object.observe API已经被strawman proposal所承认,被正式使用在V8中。自11月末开始,已经可以在Chrome Canary与开发者通道中对其进行启用。

    本文介绍Object.observe API中的基本功能及一些代码示例。

    目前为止,Object.observe API中包括如下所示的四个方法:

    • Object.observe:为对象指定监视时调用的回调函数
    • Object.unobserve:移除监视时调用的回调函数
    • Object.deliverChangeRecords:通过回调函数对对象值进行修改
    • Object.getNotifier:获取Notifier对象

    可以观察到的属性操作包括以下几种:

    • new:添加属性
    • updated:修改属性值
    • reconfigured:修改属性设定
    • deleted:删除属性

    接下来介绍如何使用Object.observe方法。

    目前(2012年12月6日)为止,如果要使用Object.observe API,需要使用Chrome Canary或Chrome Dev Channel(25.0.1337.0 dev-m以上)版本的浏览器,同时在chrome://flags/中启用“启用实验性 JavaScript”选项,如下图所示。

    简单代码示例

    Object.observe方法用于为对象指定监视到属性修改时调用的回调函数,使用方法如下所示。

    Object.observe(obj, callback);

    Object.observe方法中使用两个参数,其中第一个参数值为需要被监视的对象,第二个参数值为监视到属性修改时调用的回调函数名。可以将各对象的属性操作时生成的ChangeRecord对象数组设置为回调函数的参数。

    ChangeRecord对象拥有type、name、oldValue、object四个属性,各属性含义如下所示。

    function callback(changes) {
        changes.forEach(function(change) {
            console.log(change.type);     //对属性进行了什么操作 new/updated/reconfigured/delted
            console.log(change.name);     //属性名
            console.log(change.oldValue); //修改之前的属性值
            console.log(change.object);   //被监视的对象
        });
    }

    使用如下所示的代码,可以在任何时刻对于对象属性的上述四种操作(new/updated/reconfigured/delted)进行监视:

    var obj = {a: 1};
        Object.observe(obj, output); //为对象指定监视时调用的回调函数
    
        obj.b = 2; //添加属性
        obj.a = 2; //修改属性值
        Object.defineProperties(obj, {a: { enumerable: false}}); //修改属性设定
        delete obj.b; //删除属性  
        function output(change) {
            //回调函数,可以在此处书写在页面上的输出。
        }

    页面运行结果如下图所示(在Chrome Canary或Chrome Dev Channel(25.0.1337.0 dev-m以上)版本的浏览器中)

    创建自定义Notify对象

    可以监视到的事件并不局限于以上所述的几种,可以自定义监视事件。

    可以使用Notifier对象来自定义针对对象的可访问属性(可使用getter方法或setter方法读取或设置的属性)被修改时所触发的事件。这时,我们需要Object.getNotifier()方法获取被监视对象的Notifier对象,并使用notify方法进行属性被修改的通知。

    在以下这个示例代码中,为对象自定义time_updated事件及time_read事件并利用这两个事件监视对象的私有属性_time的读取及修改。

    var obj2 = {_time: new Date(0)};
    var notifier = Object.getNotifier(obj2); //获取Notifier对象
    Object.defineProperties(obj2, { //设置对象的可访问属性 
        _time: {
            enumerable: false,
            configrable: false
        },
        seen: {
            set: function(val) {
                var notifier = Object.getNotifier(this);
                notifier.notify({
                    type: 'time_updated', //定义time_updated事件
                    name: 'seen',
                    oldValue: this._time
                });
                this._time = val;
            },
            get: function() {
                var notifier = Object.getNotifier(this);
                notifier.notify({
                    type: 'time_read', //定义time_read事件
                    name: 'seen',
                    oldValue: this._time
                });
                return this._time;
            }
        }
    });
    Object.observe(obj2, output); //为对象指定监视时调用的回调函数
    //执行属性操作
    var first_time = obj2.seen; //触发time_read事件
    obj2.seen = new Date();      //触发time_updated事件
    var second_time = obj2.seen; //触发time_read事件

    控制回调函数的执行时间

    在默认情况下,使用Object.observe API指定的回调函数将在JavaScript脚本代码执行结束时被调用。因此如果对同一对象的同一属性执行了多次操作,回调函数中获取到的各属性值为最后一个操作结束后的值。将前面这个示例中的代码稍作修改,对使用Object.observe API进行监视的对象的属性值连续修改七次(为了避免回调函数的循环调用删除对time_read事件的监视)。

    obj3.seen = new Date(2013, 0, 1, 0, 0, 0); //触发time_updated事件
      obj3.seen = new Date(2013, 0, 2, 0, 0, 0); //触发time_updated事件
      obj3.seen = new Date(2013, 0, 3, 0, 0, 0); //触发time_updated事件
      obj3.seen = new Date(2013, 0, 4, 0, 0, 0); //触发time_updated事件
      obj3.seen = new Date(2013, 0, 5, 0, 0, 0); //触发time_updated事件
      obj3.seen = new Date(2013, 0, 6, 0, 0, 0); //触发time_updated事件
      obj3.seen = new Date(2013, 0, 7, 0, 0, 0); //触发time_updated事件
        

    页面运行结果如下图所示(在Chrome Canary或Chrome Dev Channel(25.0.1337.0 dev-m以上)版本的浏览器中)

    从这个结果中我们可以看出,在回调函数中获取到的属性值为同一个属性值(2013年1月7日)。为了强制获取事件触发后立即设置的属性值,我们需要使用Object.deliverChangeRecords方法。

    在如下所示的代码中,每次修改了属性值后,即调用Object.deliverChangeRecords方法立即调用回调函数。

    obj4.seen = new Date(2013, 0, 1, 0, 0, 0); //触发time_updated事件
      Object.deliverChangeRecords(output);       //调用回调函数
      obj4.seen = new Date(2013, 0, 2, 0, 0, 0); //触发time_updated事件
      Object.deliverChangeRecords(output);       //调用回调函数
      obj4.seen = new Date(2013, 0, 3, 0, 0, 0); //触发time_updated事件
      Object.deliverChangeRecords(output);       //调用回调函数
      obj4.seen = new Date(2013, 0, 4, 0, 0, 0); //触发time_updated事件
      Object.deliverChangeRecords(output);       //调用回调函数
      obj4.seen = new Date(2013, 0, 5, 0, 0, 0); //触发time_updated事件
      Object.deliverChangeRecords(output);       //调用回调函数
      obj4.seen = new Date(2013, 0, 6, 0, 0, 0); //触发time_updated事件
      Object.deliverChangeRecords(output);       //调用回调函数
      obj4.seen = new Date(2013, 0, 7, 0, 0, 0); //触发time_updated事件
    

    页面运行结果如下图所示(在Chrome Canary或Chrome Dev Channel(25.0.1337.0 dev-m以上)版本的浏览器中)

    从这个结果中我们可以看出,每次执行Object.deliverChangeRecords方法时都将调用回调函数在页面中输出修改后的属性值。

  • 相关阅读:
    【整理】【代码的坏味道】过长函数(Long Method)
    【整理】【代码的坏味道】重复代码(Duplicated Code)
    【原创】Winform下拉框自动选择实现
    time及各种cpu时间
    arch安装及配置xfce4桌面
    paste工具
    十分有用的cut剪切命令
    ubuntu一些脚本的执行顺序
    Linux一些经典书籍
    强大的wget下载工具
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/3427171.html
Copyright © 2011-2022 走看看