请教 ES6变量的结构赋值中,自定义弹框的例子2

请教 ES6变量的结构赋值中,自定义弹框的例子2

// 初始化一个弹出框
// 创建DOM元素
// 把弹出框插入DOM元素,再把DOM元素插入到页面中
// 显示DOM元素
(function(window, document) {
  let Msg = function(options) {
    this._init(options);
  };

  Msg.prototype._init = function({ content = '', confirm = null,
  cancel = null, userHtml = false, contentStyle = { }, contentFontSize = '1.5em'}) {
    this.content = content;
    this.confirm = confirm;
    this.cancel = cancel;
    this.userHtml = userHtml;
    this.contentStyle = contentStyle;
    this.contentFontSize = contentFontSize;

    this._createElement();
    this._show([this._el, this._overlay]);
    this._bind([this._el, this._overlay]);
  };

  Msg.prototype._bind = function([el, overlay]){
    //  这个方法在_bind方法内部使用,所以写在内部。??事件冒泡机制 11111111
    const hideMsg = function(){
        el.style.transform = 'translate(-50%, -50%) scale(0, 0)';
        overlay.style.opacity = 0;
        setTimeout(() => {
            document.body.removeChild(el);
            document.body.removeChild(overlay);
        }, 300);
        // 这个定时器跟下面confirm事件冲突了,因为事件执行完后el这个DOM元素已经没有了,confirm冒泡到el,取消事件就没办法进行了,只要在confirm事件里加阻止事件冒泡event.stopPropagation();就行了
    };
    const _this = this;
    // console.log(this) 这个this指向Msg对象
    const cancel = function(e){
    // console.log(this) 这个this指向this._el = wrap这个DOM元素,实际上指向算了吧或×这两个按钮,因为事件冒泡指向了wrap,所以要用const _this = this保留this;
        _this.cancel && _this.cancel.call(_this, e); //33333
        hideMsg();
    }
    const confirm = function(e){
        console.log(this)
        _this.confirm && _this.confirm.call(_this, e);
        hideMsg();
        alert('注册成功');
        event.stopPropagation();
    }
    overlay.addEventListener('click', cancel)
    // 事件冒泡机制,父元素监听下面所有子元素的点击事件
    el.addEventListener('click', cancel);
    // confirm确认事件比较特殊,加个冒泡。
    el.querySelector('.msg-footer-confirm-button').addEventListener('click', confirm);
  }

  Msg.prototype._createElement = function(){
    let wrap = document.createElement("div");
    wrap.className = 'msg__wrap';
    wrap.innerHTML = `<div class="msg-header">
            <span>确认删除</span>
            <span class="msg-header-close-button">×</span>
        </div>
        <div class="msg-body">
            <div class="msg-body-icon">
            <div class="msg-body-icon-wrong"></div>
            </div>
            <div class="msg-body-content"></div>
        </div>
        <div class="msg-footer">
            <button class="msg-footer-btn msg-footer-cancel-button">算了吧</button>
            <button class="msg-footer-btn msg-footer-confirm-button">好的</button>
        </div>`;
    // 在<div class="msg-body-content"></div>这里插入文本或者DOM元素
    let contentDom = wrap.querySelector('.msg-body .msg-body-content');
    const contentStyle = {
        fontSize: this.contentFontSize,
        ...this.contentStyle
    }

    for(let i in contentStyle){
        if(contentStyle.hasOwnProperty(i)){
            contentDom.style[i] = contentStyle[i];
        }
    }
    if(this.userHtml){
        contentDom.innerHTML = this.content;
    }else{
        contentDom.innerText = this.content;
    }


    let overlay = document.createElement('div');
    overlay.className = 'msg__overlay';
    this._el = wrap;
    this._overlay = overlay;
    // console.log(typeof this._el)
  }

  Msg.prototype._show = function([el, overlay]){
    document.body.appendChild(el);
    document.body.appendChild(overlay);
    // 异步操作,最后一步scale放大。
    setTimeout(() => {
        el.style.transform = 'translate(-50%, -50%) scale(1, 1)';
        overlay.style.opacity = 1;
    }, 0);
  }

  window.$Msg = Msg;
})(window, document);

看看我注释的地方对不对,还有检查一下代码。

// 1、hideMsg这个方法只能在_bind方法内部使用,所以写在内部??为什么不挂到Msg对象上?

// 2、什么时候用let ,什么时候用const,我知道let是变量,const是常量,但是const定义引用类型时,自身也能改变,我的感觉所有的常量都能使用let定义,能举几个常用的例子对比一下吗?

3、const _this = this;   _this.cancel && _this.cancel.call(_this, e); 这一步的意义到底在哪里?我利用了事件冒泡机制监听wrap下的所有点击事件,confirm事件我阻止了事件冒泡,所以我是能知道this的最终指向的。去掉这一步,然后我在事件内外打印了this,外面的指向Msg对象,里面的指向3个按钮,好像也没有影响。


正在回答 回答被采纳积分+1

登陆购买课程后可参与讨论,去登陆

3回答
樱桃小胖子 2019-10-22 18:26:48

一看就是个特别爱动脑、爱思考的同学,学习编程这一点也是非常重要的,老师也希望能够跟你有更多的技术方面的探讨,关于同学的疑问,解答如下:

http://img1.sycdn.imooc.com//climg/5daed2c609d2202818940721.jpg

关于“ _this.cancel && _this.cancel.call(_this, e);”同学的理解也是正确的,因为前面const _this = this;之后,_this改变了指向,所以_this.cancel && _this.cancel.call(_this, e);的整体指向也改变了,但是我们做一个测试,如下:

html代码如下:

http://img1.sycdn.imooc.com//climg/5daed53d09ed37b208740791.jpg

http://img1.sycdn.imooc.com//climg/5daed614095569d218230875.jpghttp://img1.sycdn.imooc.com//climg/5daed74109d466de18400539.jpg

也就是说 _this.cancel && _this.cancel.call(_this, e);整句代码的意思是判断是否有cancel,如果有,就显示“取消了,”,如果没有就不显示,不写_this.cancel && _this.cancel.call(_this, e);这句代码,的确不影响弹框的取消功能,但是,却无法显示“取消了,”这几个提示文字了。就好比确定事件里面不写_this.confirm && _this.confirm.call(_this, e);这句代码,点击弹窗中的“好的”按钮,不会显示http://img1.sycdn.imooc.com//climg/5daed9400992157203120091.jpg是一个道理。

希望可以帮到你!

  • 首先,非常感谢你们的认真的测试与解答,可能我过于较真了,不好意思。关于你们最后测试的结论,也提醒我看到原来实例化对象上也有cancel事件,但是这里的cancel事件是用来测试对象指向的,好像并没有实际作用,大多数网站都是弹窗的形式,而且我感觉定义两个相同的事件有点多余。最后,你说的确定事件显示的图片,是点击弹个框按钮显示的this.content中的内容。
    2019-10-22 20:32:24
樱桃小胖子 2019-10-20 15:24:19

1、“hideMsg这个方法只能在_bind方法内部使用,所以写在内部”这么理解是可以的,关于“为什么不挂到Msg对象上?”解释如下:

$Msg是自定义的对象,new的实例化对象的语法,在js中为$Msg赋值为Msg,而Msg的原型上面定义了很多方法,并且方法里面也有很多属性,所以实例化$Msg就相当于实例化Msg,这样实例化的时候可以调用这些属性和方法。

2、大部分情况下const的使用率比let高,由于const一旦定义就不可改变,所以一般为了代码的性能和稳定性,建议使用const,除非一定要改变变量的值,再使用let

3、关于 const _this = this,当前代码中的this是指向实例,相当于父级,指向指不到子级中,所以需要一个变量 _this存储this得指向,_this.cancel && _this.cancel.call(_this,e);这句代码的作用是获取用户是不是点击确认按钮了,然后执行一下操作

希望可以帮到你,如果还有哪里不懂,可以继续提问

祝学习愉快~


  • 1、hideMsg这个方法可以挂载到Img对象上,但是因为只在_bind方法内部使用,所以写在了内部。 3、const _this = this; // console.log(this) 这个this指向Msg对象 const cancel = function(e){ // console.log(this) 这个this指向this._el = wrap这个DOM元素,实际上指向算了吧或×这两个按钮,因为事件冒泡指向了wrap,所以要用const _this = this保留this; _this.cancel && _this.cancel.call(_this, e); hideMsg(); } 我这里都注释清楚了,如果不保留this,外面打印this是Msg对象,里面打印的是算了吧或×这两个按钮对象。是不是点击按钮是由点击事件监听的吧。 这句代码的意思是Msg对象存在cancel事件并且把事件对象的指向改变为Msg对象,因为它们原来是指向两个按钮的。所以我觉得这句代码没有实际的意义,希望能有合理的解释。
    2019-10-21 04:38:15
好帮手慕糖 2019-10-19 13:50:53

同学你好,1、是的哦,因为其他的地方不使用,可以不挂载到Msg对象上。

2、let声明的是变量,也就是能够改变的量。

 使用const声明的是常量,保存的是内存地址,可以给对象或数组添加属性或元素,但是不能重新复写,也就是重新赋值。

如果分不清楚什么时候用let,什么时候用const,都使用let定义也没有问题。

3、&&是逻辑运算符,是逻辑与;

这句话的意思,是_this.cancel若是存在的话为真,否则为假。&&逻辑与运算符,若第一个为假的话,就直接返回了,为真的话,会接着执行第二个,就执行了_this.cancel.call(_this, e); 

(1)外面的this指向的是Msg这个对象,但是在cancel这个函数中,this是不能使用Msg对象的,所以使用一个变量(_this)来保存这个this(指向Msg对象的this),

http://img1.sycdn.imooc.com//climg/5daaa25309623b6711950290.jpg

(2)cancel是_init的这个cancel哦,使用this的话,是可以挂载到实例化对象上的。

http://img1.sycdn.imooc.com//climg/5daaa41e093e932a12760246.jpg

所以应该使用指向实例化对象的this去访问它。

希望能帮助到你,祝学习愉快!

  • 你整个解答答非所问,避重就轻,把我所知道的知识点重复了一遍,你不懂就别答我的问题,换个老师行吗,还有求你以后别答我的问题了?
    2019-10-19 23:13:20
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师