为了账号安全,请及时绑定邮箱和手机立即绑定

widget.js中的构造函数代码this.handlers ={};需要去除。要在window.js的Window构造函数中把this.handlers ={};补上。

抽取widget抽象类:widget.js中的构造函数

 function Widget(){
      this.handlers ={};
}

,和window.js里的

function Window(){
    this.handlers ={};
}

这个this.handlers ={};可以去除也只能去除一个【或者两个都保存,保存的话引用的是window自己的handles】。而且应该要去除Widget里的代码

从面向对象的角度来说:对象的主要用途就是本身的属性,方法,其实方法也是xxxObj.xxfun(),也可以理解为一种属性。就是老师说的字典,从这节的代码来看,主要的作用是抽取handles这个obj放置在widget中,【PS:handles里面放的是各个类型的事件数组】。源代码中抽取了widget.js,然后再window.js中$.extends({},new widget.Widget(),{xxx:XXX})中就会把后面两个对象的属性和方法都挂载到了第一个对象{}上了。这时候,其实可以widget.js下的

function Widget(){
   this.handlers ={};
}

里的this.handlers ={};注释掉。因为function Window(){}构造函数中已经包含了这个定义了

function Window(){   
     XXXX..;
    this.handlers = {};
}

而main.js中实例化对象 var win = new w.Window();new的过程中自然就拥有了Window构造函数中的handles对象。实例win当然可以正确引用到handle。而且,这样引用的handler是自己实例中的handle,搜索树会比较短。效率比较高。如果去除window构造函数的this.handlers = {};这里引用的是window.js中

$.extends({},new widget.Widget(),{xxx:XXX})

new new widget.Widget()产生的handles了。【ps:注意new widget.Widget()之后就产生了一个对象,包含了{key:val}这里就包含了handle:{}这样的key,val了】。

这时候(就是去除Window构造函数的this.handlers = {};不去除widget.js的语句)那么搜索的时候搜索的是Window构造函数原型链上的handler实例。所有的window对象都共享了这个prototype上的handle实例,所以会有bug。假设一个场景(index.html上初始化两个按钮,一个绑定了很多事件,一个不绑定)那么先点击绑定事件的按钮,弹出窗口(这个时候的窗口实例已经绑定了多个事件),然后关闭窗口,再点击不绑定事件的按钮,那么同样会弹出多个事件,因为共享了这个原型对象的handler实例。

简单的说。 Window.prototype= $.extend({},new widget.Widget(), {xxxx}这句代码执行后,如果 Window构造函数中去除this.handlers = {};,那么他找的是Window原型树的handle;如果去除了widget构造函数的this.handlers = {};那么找的是自己的handlers。

-----------------------------------------------------------------------------------------------------------------------

贴上主要代码

main.js,已经将jquery-ui下载到本地了

/**
 * Created by Administrator on 2015/7/21.
 */
require.config({
    paths:{
        jquery:'jquery-2.1.1',
        jqueryUI: 'jquery-ui'
    }
});
require(['jquery','window'],function($,w){
    $(function(){
       $("#btna").on('click',function(){
           var win = new  w.Window();
           win.alert({
               width:300,
               height:150,
               y:50,
               content:'hello',
               title:'title',
               hasCloseBtn:true,
               skinClassName:'window_skin_a',
               textAlertBtn:'hello',
               dragHandle:'.window_header'
           }).on("alert",function(){
                alert("first alert");
            }).on('alert',function(){
               alert('second alert');
           }).on('alert',function(){
               alert("third alsert");
           }).on('close',function(){
               alert("second close");
           })

       });
        $("#btnb").on('click',function(){
            var win = new  w.Window();
            win.alert({
                width:300,
                height:150,
                y:50,
                content:'hello',
                title:'title',
                hasCloseBtn:true,
                skinClassName:'window_skin_a',
                textAlertBtn:'hello',
                dragHandle:'.window_header'
            });

        });


    })

})

widget.js

/**
 * Created by Administrator on 15-7-25.
 */
define(function(){
    function Widget(){
       // this.handlers = {};
    }
    Widget.prototype = {
        on:function(type ,handler){
            if(typeof this.handlers[type]=='undefined'){
                this.handlers[type] =[];
            }
            this.handlers[type].push(handler);
            return this;
        },
        fire:function(type,data){
            if(this.handlers[type] instanceof  Array){
                var handles= this.handlers[type];
                for(var i= 0,len=this.handlers[type].length;i<len;i++){
                    handles[i](data);
                }
            }
        }

    }
    return {
        Widget:Widget//这里不能加(),不然就跑方法了。
    }
});

window.js

define(['widget','jquery','jqueryUI'],function(widget,$,$UI){
    function Window(){
        this.cfg={
            width:500,
            height:300,
            content:'',
            handler4AlertBtn:null,
            handler4CloseBtn:null,
            hasMask:true,
            title:'system title',
            text4AlertBtn:'sure',
            skinClassName:'',
            hasCloseBtn:false,
            isDraggable:true,
            dragHandle:null

        };
        this.handlers = {};

    };
    Window.prototype= $.extend({},new widget.Widget(), {
        alert:function(cfg){
            var CFG = $.extend(this.cfg,cfg);
            var that = this;
            var boundingBox = $('<div class="window_boundingBox">' +
                '<div class="window_header">'+CFG.title+'</div>' +
                '<div class="window_body">'+CFG.content+'</div>' +
                '<div class="window_footer"><input type="button" class="window_alertBtn" value="'+CFG.text4AlertBtn+'"/></div>' +
                '</div>');
            var mask = null;
            if(CFG.hasMask){
                mask = $('<div class="window_mask"></div>');
                mask.appendTo("body");
            }
            if(CFG.isDraggable){
                if(CFG.dragHandle){
                    boundingBox.draggable({handle:CFG.dragHandle});
                }else{
                    boundingBox.draggable();
                }
            }
            boundingBox.appendTo("body");
            if(CFG.skinClassName!==""){
                boundingBox.addClass(CFG.skinClassName);
            }
            if(CFG.hasCloseBtn){
                var closeBtn = $('<span class="window_closeBtn">X</span>');
                boundingBox.find(".window_header").append(closeBtn);
                closeBtn.on("click",function(){
                    // CFG.handler4CloseBtn&&CFG.handler4CloseBtn();
                    that.fire("close");
                    boundingBox.remove();
                    mask&& mask.remove();
                });

            }

            if(CFG.handler4CloseBtn){
                this.on('close',CFG.handler4AlertBtn);
            }
            if(CFG.handler4AlertBtn){
                this.on('alert',CFG.handler4CloseBtn);
            }

            var btn = boundingBox.find(".window_footer .window_alertBtn");

            btn.on("click",function(){
               // CFG.handler4AlertBtn&&CFG.handler4AlertBtn();
                that.fire("alert");
                boundingBox.remove();
                mask&& mask.remove();
            });
            boundingBox.css({
                width:CFG.width+"px",
                height:CFG.height+"px",
                left:(CFG.x||(window.innerWidth-CFG.width)/2)+'px',
                top:(CFG.y||(window.innerHeight-CFG.height)/2)+'px'
            });
            return this;

        },
        prompt:function(){
            console.log("prompt");
        },
        confirm:function(){
            console.log("confirm");
        }
    });


    return {Window:Window};
})

index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
    <link href="css/base.css" type="text/css" rel="stylesheet"/>
    <link href="css/window.css" type="text/css" rel="stylesheet"/>
    <script src="js/require.js" data-main="js/main.js"></script>
</head>
<body>
    <input type="button" value="alert" id="btna"/>
    <input type="button" value="alert" id="btnb"/>

</body>
</html>


正在回答

3 回答

这个最佳的解决方案不是把父类的this.handlers ={};移除 放入到windows

因为现在只有这么一个属性。所以你可以这么做。如果有上百个。你要每个子类都这么写吗?那继承就没意义了

在子类中以子类作用域调用父类构造来解决这个问题


子类可以加入:

widget.Widget.call(this);

0 回复 有任何疑惑可以回复我~

之前就看过不甚理解,现在看完高程上的原型章节再回过头来看楼主的说法,加深不少印象,谢谢

0 回复 有任何疑惑可以回复我~

我也同意你的说法

0 回复 有任何疑惑可以回复我~

举报

0/150
提交
取消
阿当大话西游之WEB组件
  • 参与学习       26371    人
  • 解答问题       275    个

衡量攻城师能力是否成熟的重要指标,本课程会以弹窗组件为例

进入课程

widget.js中的构造函数代码this.handlers ={};需要去除。要在window.js的Window构造函数中把this.handlers ={};补上。

我要回答 关注问题
意见反馈 帮助中心 APP下载
官方微信