美文网首页
IFE2017,动态数据绑定(二)学习笔记

IFE2017,动态数据绑定(二)学习笔记

作者: 沈墨空 | 来源:发表于2017-04-01 17:29 被阅读0次

    自定义事件

    我们知道JS里绑定事件有addEventListener()这个方法。
    在JS中我们可以这样创建一个自定义事件

    var container = document.getElementById("container");
    // 创建事件
    var evt = document.createEvent("Event");
    // 初始化事件
    evt.initEvent("customEvent",true,true);
    // 监听事件
    container.addEventListener("customEvent",function(){
      // do something
    },false);
    // 触发事件
    container.dispatchEvent(evt);
    

    这种做法有两个问题,一个是兼容性问题,IE8及以下不支持这种写法;另一点则是事件必须绑定到DOM节点上。

    那么不依赖addEventListener()能否模拟出一个自定义事件呢
    这时候我们需要了解一下观察者模式

    观察者模式

    观察者模式又叫做发布订阅模式,它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生改变时就会通知所有观察着对象。它是由两类对象组成,主题和观察者,主题负责发布事件,同时观察者通过订阅这些事件来观察该主体,发布者和订阅者是完全解耦的,彼此不知道对方的存在,两者仅仅共享一个自定义事件的名称。

    发布者就相当于广播事件的人,而订阅者则是订阅了这个广播,当收到事件发生的消息后就执行一系列动作(回调函数)。

    一个最简单的观察者模式就像下面这样:

    function Event(){
        // 订阅者(回调函数)队列
        this.callbacks = {};
        that = this;
    
        // 订阅(绑定)事件
        this.on = function (key,callback){
            that.callbacks[key] = callback;
        };
        // 发布(触发)事件
        this.emit = function (key,...arg){
            if(that.callbacks.hasOwnProperty(key))that.callbacks[key](...arg);
        }
    }
    

    上面这种写法每个事件只能接受一个回调函数,而有时候我们会对同一个事件执行多个回调函数,所以我们往往会把callback[key]做成一个数组,存放未知个数的回调函数。

    如下:

    function Event(){
        // 订阅者(回调函数)队列
        this.callbacks = {};
    
        // 订阅(绑定)事件 
        this.on = function(attr,callback){
            if (typeof this.callbacks[attr] === 'undefined') this.callbacks[attr] = [];
            this.callbacks[attr].push(callback);
        };
    
        // 发布(触发)事件
        this.emit = function(attr,val){
            this.callbacks[attr].forEach(function(callback){
                callback(attr,val);
            });
        };
    }
    

    回到题目

    题目要求我们实现watch这个api:

    let app1 = new Observer({
             name: 'youngwind',
             age: 25
     });
    
     // 你需要实现 $watch 这个 API
     app1.$watch('age', function(age) {
             console.log(`我的年纪变了,现在已经是:${age}岁了`)
     });
    
     app1.data.age = 100; // 输出:'我的年纪变了,现在已经是100岁了'
    

    那么我们需要先在Observer构造函数中创建一个watch自定义事件
    Observer.prototype.watch = new Event();

    接着绑定事件
    Observer.prototype.$watch = function(key,callback){ this.watch.on(key,callback); }

    最后在Observer的setter中触发事件

    var that = this;
    Object.defineProperty(this.data,key,{
      set: function (newVal){
          ...(略)
          that.watch.emit(key,newVal);
        };
      },
      get:...(略)
    });
    

    这样就完成了数据变化时触发回调函数的绑定

    相关文章

      网友评论

          本文标题:IFE2017,动态数据绑定(二)学习笔记

          本文链接:https://www.haomeiwen.com/subject/mzyqottx.html