什麼是組件?

對面向對象的深入應用(UI組件、功能組件)
將配置參數、方法、事件,三者分離
創建自定義事件:
有利於多人協作開發;
如何去掛載自定義事件與事件函數

自定義事件:主要與函數有關,讓函數具備事件某些特性
(比如,多个函数也可如事件都执行,而不是像同名函数后覆盖前)

原理:

window.onload = function () {
    var _div = document.getElementById('div1')
    var _span = document.getElementById('span1')

    bind(_div, 'click', function () {
        console.log(1);
    })
    bind(_div, 'click', function () {
        console.log(2);
    })

    bind(_span, 'show', function () {
        console.log(3);
    })
    bind(_span, 'show', function () {
        console.log(4);
    })
    bind(_span, 'hide', function () {
        console.log(5);
    })

//觸發自定義事件: 

    autoEvent(_span, 'show') // 3,4
    autoEvent(_span, 'hide') // 3,4


    function bind(obj, events, fn) {   //建立关系 ;
        //obj:楼层;
        //events:书架
        //fn:一本书

        obj.listeners = obj.listeners || {} //樓層
        obj.listeners[events] = obj.listeners[events] || []; //樓層下創建書架
        obj.listeners[events].push(fn); //push方法把對應的書存到書架下


        if (obj.addEventListener) {
            obj.addEventListener(events, fn, false)
        }
        else {
            obj.attachEvent('on' + events, fn)
        }
    }

    function autoEvent(obj, events) {   //主动触发自定义事件;
        for (var i = 0; i < obj.listeners[events].length; i++) {
            obj.listeners[events][i]();   //循環數組執行即可
        }

    }

}

改寫實例:

window.onload = function () {
    var d1 = new Drag()
    var d2 = new Drag()
    var d3 = new Drag()
    var d4 = new Drag()
    d1.init({
        id: 'div1'
    })
    d2.init({
        id: 'div2'
    })
    bind(d2, '_down', function () {
        document.title = 'down'
    })
    d3.init({
        id: 'div3'
    })
    bind(d3, '_up', function () {
        document.title = 'up'
    })
    d4.init({
        id: 'div4'
    })
    bind(d4, '_up', function () {
        document.title = 'bybybybyb'
    })

//所以,最大的好處:如果想讓最後一個變大,只需要再綁定一次即可;而不是寫在原有代碼裏;

    bind(d4, '_up', function () {
        document.getElementById('div4').style.width = '200px'
    })
}
function Drag() {
    this.obj = null;
    this.disX = 0;
    this.dixY = 0;
    this.settings = {}
}
Drag.prototype.init = function (opt) {
    this.obj = document.getElementById(opt.id)
    var _this = this;
    extend(this.settings, opt)
    this.obj.onmousedown = function (ev) {
        var ev = ev || event;
        _this.fnDown(ev)
//執行
        autoEvent(_this, '_down')

        document.onmousemove = function (ev) {
            var ev = ev || event;
            _this.fnMove(ev)
        }
        document.onmouseup = function () {
            _this.fnUp();
//執行
            autoEvent(_this, '_up')

        }
        return false //最後加阻止默認事件;
    }
}
Drag.prototype.fnDown = function (ev) {
    this.disX = ev.clientX - this.obj.offsetLeft;
    this.disY = ev.clientY - this.obj.offsetTop;
}
Drag.prototype.fnMove = function (ev) {
    this.obj.style.left = ev.clientX - this.disX + 'px'
    this.obj.style.top = ev.clientY - this.disY + 'px'
}
Drag.prototype.fnUp = function () {
    document.onmousemove = document.onmouseup = null;
}
function extend(o1, o2) {
    for (var attr in o2) {
        o1[attr] = o2[attr]
    }
}
function bind(obj, events, fn) {
    obj.listeners = obj.listeners || {};
    obj.listeners[events] = obj.listeners[events] || [];
    obj.listeners[events].push(fn);

    if (obj.nodeType) { //判斷是否為dom元素
        if (obj.addEventListener) {
            obj.addEventListener(events, fn, false)
        }
        else {
            obj.attachEvent('on' + events, fn)
        }
    }
}

function autoEvent(obj, events) {
    if (obj.listeners && obj.listeners[events]) { //判斷是否存在
        for (var i = 0; i < obj.listeners[events].length; i++) {
            obj.listeners[events][i]()
        }
    }

}