问题复现
首先复制官方代码,可以显示轮播图。
但是出现的情况是,点击右上角的切换下一张,直接切换了两张轮播图。
问题跟踪
chrome 浏览器F12加断点。首先已知这个系统自带的轮播图插件是基于bootstrap的,打开这个js,然后搜索carousel
在407行,找到如下代码
Carousel.prototype.next = function () {
if (this.sliding) return
return this.slide('next')
}
如果判断为真,直接返回。否则,进入this.slide('next')
断点进入方法。417行
Carousel.prototype.slide = function (type, next) {
...
...
//这里把sliding设置为true,那么407的方法应该直接return的,而断点时发现,那里为false,
//所以重点关注这个值
this.sliding = true
...
var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
if ($.support.transition && this.$element.hasClass('slide')) {
//如果进入这个代码块,未更改sliding的值,依然为true
$next.addClass(type)
if (typeof $next === 'object' && $next.length) {
$next[0].offsetWidth // force reflow
}
$active.addClass(direction)
$next.addClass(direction)
$active
.one('bsTransitionEnd', function () {
$next.removeClass([type, direction].join(' ')).addClass('active')
$active.removeClass(['active', direction].join(' '))
that.sliding = false
setTimeout(function () {
that.$element.trigger(slidEvent)
}, 0)
})
.emulateTransitionEnd(Carousel.TRANSITION_DURATION)
} else {
$active.removeClass('active')
$next.addClass('active')
//如果进入这个代码块,则重置为false
this.sliding = false
this.$element.trigger(slidEvent)
}
isCycling && this.cycle()
return this
}
观察代码,如果进入else,407行的this.sliding为false。而根据断点调试,的却进入了else分支。
观察if判断
if ($.support.transition && this.$element.hasClass('slide'))
断点发现&&前为true,也即&&后的判定,我们要把他改为true,这里判定了element是否有slide class。
解决问题
为这个element设置slide的class,问题解决
echo Carousel::widget([
'items' => $slides,
'options'=>['class'=>'slide']
]);
深入研究
断点跟踪框架中的Carousel控件,它根据options参数来设置class属性,而代码中的却没有默认设置slide的class。
问题已经解决,但是为什么会出现这种问题就很费解了。