• bootstrap 通过js代码创建和关闭插件


    插件的创建机制
    默认情况下,boostrap.js文件被页面加载执行完成后,boostrap会自动根据html元素的data-toggle属性和相关class创建插件对象。有时候,我们不希望boostrap插件的行为影响到整个页面,希望可以精准地在一个 指定的html元素上创建插件。要想达到这个目的,需要两个步骤:
    1. 关闭插件的默认行为。
    2. 在指定的html元素重新创插件。
     
    第一步只需要很简单的一行代码就可以达到目的:
    $(document).off(".data-api");
    这行代码是关闭.data-api名字空间下的所有事件处理器,而boostrap所有插件的事件类型都是在.data-api名字空间下的,所以,这样就可以让所有插件失效。
     
    第二步就比较麻烦,需要搞清楚bootstrap默认是怎样创建插件的。下面以collapse插件为例看看插件的创建过程:
    function getTargetFromTrigger($trigger) {
    var href
    var target = $trigger.attr('data-target')
    || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^s]+$)/, '') // strip for ie7
     
    return $(target)
    }
     
    function Plugin(option) {
    return this.each(function () {
    var $this = $(this)
    var data = $this.data('bs.collapse')
    var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
     
    if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
    if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
    if (typeof option == 'string') data[option]()
    })
    }
     
    var old = $.fn.collapse
     
    $.fn.collapse = Plugin
    $.fn.collapse.Constructor = Collapse
     
    $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
    var $this = $(this)
     
    if (!$this.attr('data-target')) e.preventDefault()
     
    var $target = getTargetFromTrigger($this)
    var data = $target.data('bs.collapse')
    var option = data ? 'toggle' : $this.data()
     
    Plugin.call($target, option)
    })
    通过上面的一段代码,可以得到4个重要的结论:
    1. Plugin函数表名,bootstrap插件实际上是一个jquery插件。
    2. document元素所有子元素中,带有属性data-toggle="collapse"的元素上注册了click事件.
    3. 带有data-toggle="collapse"属性的元素只是触发器(trigger), data-target指向的元素才是collapse插件创建的目标元素。
    4. trigger第一次执行click事件处理器时才会创建collapse插件。
    有了这4个结论,就很容易想到,只需把click.bs.collapse.data-api事件注册到指定的知道的元素上即可随意控制collapse插件的影响范围,即:把document替换成你想要的element。
     
    collapse插件是一个很典型的bootstrap插件,在boostrap中,绝大多数插件都和它类似,通过在document上注册事件作为插创建的入口。因此可以说,boostrap插件的手动创建过程,就是在指定的元素上重新注册事件。
     
    下面来具体看一下每一个插件的创建和和关闭。
     
    Modal
    默认情况下,在带有data-toggle="modal"的元素上注册click.bs.modal.data-api的处理函数,当触发这个元素的click事件后,会在data-target或href属性指向的元素上创建Modal插件。对真正的modal来说,这个元素只是一个trigger, model之后的行为和它再无关系。modal创建可以忽略这个trigger, $(elem).modal("show")即可在指定的元素上创建,$(elem).modal("hide")关闭。
     
    Dropdown
    创建:
    $(elem).dropdown();
    if(!$(document).data("dropdown_inited")){
    $(document).data("dropdown_inited", true);
    $(document).dropdown();
    }
    droapdown方法会把Dropdown的toggle方法注册到elem的click事件上,toggle方法实现了dropdwon的所有行为。只是这样还不行,因为这个插件还有一个行为:点击其他任何地方都会导致原来已经弹出的dropdwon收起,所以还要在document创建一个用于处理全局点击事件的drapdown。不要担心这个全局的dropdown会造成不良影响,它的唯一作用是收起已经打开的dropdown。
    关闭:
    $(elem).off("click.bs.dropdown");
     
    Tab
    创建
    function clickHandler(e) {
    e.preventDefault()
    let Plugin = $(this).tab;
    Plugin.call($(this), 'show')
    }
    $(elem)
    .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
    .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
    关闭
    $(elem)
    .off('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
    .off('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
     
    Tooltip, Popover
    创建
    $(elem).tooltip();
    $(elem).popover();
    关闭
    默认情况下会在elem上注册mouseenter, mouseleave或focusin, focusout或click事件,关闭是需要注销这几个事件。这些事件的注册行为取决于options的trigger属性,默认值是"hover focus"
    function off(plugin){
    let triggers = plugin.options.trigger.split(' ')
    for (var i = triggers.length; i--;) {
    let trigger = triggers[i]
     
    if (trigger == 'click') {
    plugin.$element.off('click.' + plugin.type)
    } else if (trigger != 'manual') {
    let eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
    let eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
     
    plugin.$element.off(eventIn + '.' + plugin.type)
    plugin.$element.off(eventOut + '.' + plugin.type)
      }
    }
    plugin.$element.data("bs"+plugin.type, null);
    }
    let plugin =$(elem).data('bs.tooltip')
    if(plugin) off(plugin);
    plugin = $(elem).data('bs.popover');
    if(plugin off(plugin);
     
    Popover是从Tooltip继承而来,它们的行为处理方式是一样的。
     
    Alert
    创建
    $(elem).alert();
    关闭
    $(elem).off("click", [data-dismiss="alert"]);
     
    Button
    创建
    $(elem).button();
    关闭
    button插件不需关闭,bootstrap没有在它在元素上注册事件处理,造成干扰。
     
    Collapse
    创建:
    collapse默认在trigger上注册click事件处理器函数,这个函数先从trigger的data-taget或href上得到创建collapse的目标元素,然后在这个目标元素上创建collapse
    function getTargetFromTrigger($trigger){
    let href
    let target = $trigger.attr('data-target')
    || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^s]+$)/, '') // strip for ie7
     
    return $(target)
    }
    function clickHandler(e){
    let $this = $(this)
     
    if (!$this.attr('data-target')) e.preventDefault()
     
    let $target = getTargetFromTrigger($this)
    let data = $target.data('bs.collapse')
    let option = data ? 'toggle' : $this.data()
     
    let Plugin = elem.collapse;
    Plugin.call($target, option)
    }
    $(elem).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', clickHandler);
     
    关闭
    $(elem).off(".collapse.data-api", '[data-toggle="collapse"]', clickHandler);
     
    let triggers = $(elem).find('[data-toggle="collapse"]');
    triggers.foreach(function(){
    let $this = $(this)
    let $target = getTargetFromTrigger($this)
    $target.data('bs.collapse', null);
    });
     
    Carousel
    创建
    trigger的点击事件处理函数
    function clickHandler(e){
    let href
    let $this = $(this)
    let $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^s]+$)/, '')) // strip for ie7
    if (!$target.hasClass('carousel')) return
    let options = $.extend({}, $target.data(), $this.data())
    let slideIndex = $this.attr('data-slide-to')
    if (slideIndex) options.interval = false
     
    let Plugin = $this.carousel;
    Plugin.call($target, options)
     
    if (slideIndex) {
    $target.data('bs.carousel').to(slideIndex)
    }
    e.preventDefault()
    }
    添加事件处理函数
    $(elem)
    .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
    .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
    ;
    关闭:
    销毁trigger关联的元素上的carousel
    function destroy(triggers){
    triggers.foreach(function(){
    let href
    let $this = $(this)
    let $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^s]+$)/, ''));
    if (!$target.hasClass('carousel')) return
    $target.foreach(function(){
    let $item = $(this);
    $item.data('bs.carousel', null);
    });
    });
    }
    关闭事件处理
    $(elem)
    .off('click.bs.carousel.data-api', '[data-slide]', clickHandler)
    .off('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
    ;
    销毁所有trigger关联元素上的carousel
    let triggers = elem.find("[data-slide]");
    destroy(triggers);
    triggers = elem.find("[data-slide-to]");
    destroy(triggers);

  • 相关阅读:
    EntityFramework Code-First 简易教程(五)-------领域类配置
    EntityFramework Code-First 简易教程(四)-------继承策略
    Springboot整合mybatis:Invalid bound statement (not found)
    centos7服务器安装mysql8
    redis-Jedis
    redis学习-集群模式cluster
    redis学习-发布订阅
    redis学习-持久化机制
    redis学习-简单事务
    redis学习-哨兵模式
  • 原文地址:https://www.cnblogs.com/brandonli/p/9859205.html
Copyright © 2020-2023  润新知