mirror of https://github.com/layui/layui
feat(tabs): 支持自定义切换标签时的过渡效果
parent
ece68e117e
commit
c5dfff8016
|
@ -99,6 +99,22 @@
|
||||||
|
|
||||||
`false`
|
`false`
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>anim <sup>2.11.4</sup></td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
自定义切换标签时的过渡效果。例如:
|
||||||
|
|
||||||
|
`['layui-anim layui-anim-fadein', 'layui-anim layui-anim-fadeout']`
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>Array</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
undefined
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
@ -8,6 +8,8 @@ layui.define('component', function(exports) {
|
||||||
|
|
||||||
var $ = layui.$;
|
var $ = layui.$;
|
||||||
|
|
||||||
|
var isSupportsAnimationend = supportsAnimationEnd();
|
||||||
|
|
||||||
// 创建组件
|
// 创建组件
|
||||||
var component = layui.component({
|
var component = layui.component({
|
||||||
name: 'tabs', // 组件名
|
name: 'tabs', // 组件名
|
||||||
|
@ -25,7 +27,8 @@ layui.define('component', function(exports) {
|
||||||
CLOSE: 'layui-tabs-close',
|
CLOSE: 'layui-tabs-close',
|
||||||
BODY: 'layui-tabs-body',
|
BODY: 'layui-tabs-body',
|
||||||
ITEM: 'layui-tabs-item',
|
ITEM: 'layui-tabs-item',
|
||||||
CARD: 'layui-tabs-card'
|
CARD: 'layui-tabs-card',
|
||||||
|
ANIM_END_EVENT_NAME: 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend'
|
||||||
},
|
},
|
||||||
|
|
||||||
// 渲染
|
// 渲染
|
||||||
|
@ -97,7 +100,12 @@ layui.define('component', function(exports) {
|
||||||
if ('index' in options && data.index != options.index) {
|
if ('index' in options && data.index != options.index) {
|
||||||
that.change(that.findHeaderItem(options.index), true);
|
that.change(that.findHeaderItem(options.index), true);
|
||||||
} else if (data.index === -1) { // 初始选中项为空时,默认选中第一个
|
} else if (data.index === -1) { // 初始选中项为空时,默认选中第一个
|
||||||
that.change(that.findHeaderItem(0), true);
|
var activeElem = that.findHeaderItem(0);
|
||||||
|
if(activeElem.length > 0){
|
||||||
|
activeElem.addClass(component.CONST.CLASS_THIS);
|
||||||
|
that.findBodyItem(activeElem.attr('lay-id') || 0).addClass(component.CONST.CLASS_SHOW);
|
||||||
|
that.change(activeElem, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化滚动结构
|
// 初始化滚动结构
|
||||||
|
@ -133,7 +141,9 @@ layui.define('component', function(exports) {
|
||||||
var trigger = options.trigger + TRIGGER_NAMESPACE;
|
var trigger = options.trigger + TRIGGER_NAMESPACE;
|
||||||
var elemHeaderItem = that.documentElem ? that.headerElem[1] : that.headerElem.join('');
|
var elemHeaderItem = that.documentElem ? that.headerElem[1] : that.headerElem.join('');
|
||||||
delegatedElement.off(trigger).on(trigger, elemHeaderItem, function() {
|
delegatedElement.off(trigger).on(trigger, elemHeaderItem, function() {
|
||||||
that.change($(this));
|
if(this !== that.data().thisHeaderItem[0]){
|
||||||
|
that.change($(this));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 窗口 resize 事件
|
// 窗口 resize 事件
|
||||||
|
@ -270,7 +280,11 @@ layui.define('component', function(exports) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 移除元素
|
// 移除元素
|
||||||
that.findBodyItem(layid || index).remove();
|
// 延迟移除元素,否则会导致元素移除后,无法触发 animationend 事件
|
||||||
|
var waitRemoveEl = that.findBodyItem(layid || index)
|
||||||
|
setTimeout(function(){
|
||||||
|
waitRemoveEl.remove();
|
||||||
|
}, 450)
|
||||||
thisHeaderItem.remove();
|
thisHeaderItem.remove();
|
||||||
|
|
||||||
that.roll('auto', index);
|
that.roll('auto', index);
|
||||||
|
@ -415,8 +429,16 @@ layui.define('component', function(exports) {
|
||||||
.removeClass(component.CONST.CLASS_THIS);
|
.removeClass(component.CONST.CLASS_THIS);
|
||||||
|
|
||||||
// 执行标签内容切换
|
// 执行标签内容切换
|
||||||
that.findBodyItem(layid || index).addClass(component.CONST.CLASS_SHOW)
|
var bodyElem = that.findBodyItem(layid || index);
|
||||||
.siblings().removeClass(component.CONST.CLASS_SHOW);
|
if(
|
||||||
|
isSupportsAnimationend
|
||||||
|
&& options.anim
|
||||||
|
&& layui.type(options.anim) === 'array'
|
||||||
|
){
|
||||||
|
that.applyAnim(data.thisBodyItem, bodyElem);
|
||||||
|
}else{
|
||||||
|
bodyElem.addClass(component.CONST.CLASS_SHOW).siblings().removeClass(component.CONST.CLASS_SHOW);
|
||||||
|
}
|
||||||
|
|
||||||
that.roll('auto', index);
|
that.roll('auto', index);
|
||||||
|
|
||||||
|
@ -432,6 +454,37 @@ layui.define('component', function(exports) {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Class.prototype.applyAnim = function(oldActiveContentEl, activeContentEl){
|
||||||
|
var that = this;
|
||||||
|
var options = that.config;
|
||||||
|
|
||||||
|
var onlyIn = !isConnectedElement(oldActiveContentEl[0]) || oldActiveContentEl[0] === activeContentEl[0]; // 处理初始渲染
|
||||||
|
|
||||||
|
var animInClass = options.anim[0];
|
||||||
|
var animOutClass = options.anim[1];
|
||||||
|
var transitionOut = function(cb){
|
||||||
|
oldActiveContentEl
|
||||||
|
.addClass(animOutClass)
|
||||||
|
.one(component.CONST.ANIM_END_EVENT_NAME, function() {
|
||||||
|
oldActiveContentEl.removeClass(component.CONST.CLASS_SHOW).removeClass(animOutClass);
|
||||||
|
cb && cb();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
var transitionIn = function(){
|
||||||
|
activeContentEl
|
||||||
|
.addClass(component.CONST.CLASS_SHOW)
|
||||||
|
.addClass(animInClass)
|
||||||
|
.one(component.CONST.ANIM_END_EVENT_NAME, function() {
|
||||||
|
activeContentEl.removeClass(animInClass);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if(onlyIn){
|
||||||
|
transitionIn();
|
||||||
|
}else{
|
||||||
|
transitionOut(transitionIn);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 渲染标签头部项
|
* 渲染标签头部项
|
||||||
* @param {Object} opts - 标签项配置信息
|
* @param {Object} opts - 标签项配置信息
|
||||||
|
@ -703,12 +756,13 @@ layui.define('component', function(exports) {
|
||||||
var container = that.getContainer();
|
var container = that.getContainer();
|
||||||
var thisHeaderItem = container.header.items.filter('.'+ component.CONST.CLASS_THIS);
|
var thisHeaderItem = container.header.items.filter('.'+ component.CONST.CLASS_THIS);
|
||||||
var index = thisHeaderItem.index();
|
var index = thisHeaderItem.index();
|
||||||
|
var layid = thisHeaderItem.attr('lay-id');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
options: options, // 标签配置信息
|
options: options, // 标签配置信息
|
||||||
container: container, // 标签容器的相关元素
|
container: container, // 标签容器的相关元素
|
||||||
thisHeaderItem: thisHeaderItem, // 当前活动标签头部项
|
thisHeaderItem: thisHeaderItem, // 当前活动标签头部项
|
||||||
thisBodyItem: that.findBodyItem(index), // 当前活动标签内容项
|
thisBodyItem: that.findBodyItem(layid || index), // 当前活动标签内容项
|
||||||
index: index, // 当前活动标签索引
|
index: index, // 当前活动标签索引
|
||||||
length: container.header.items.length // 标签数量
|
length: container.header.items.length // 标签数量
|
||||||
};
|
};
|
||||||
|
@ -815,5 +869,42 @@ layui.define('component', function(exports) {
|
||||||
component.render();
|
component.render();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测当前环境是否支持动画结束事件
|
||||||
|
* @returns {boolean} - 如果支持动画结束事件则返回 true,否则返回 false
|
||||||
|
*/
|
||||||
|
function supportsAnimationEnd() {
|
||||||
|
if(typeof AnimationEvent !== 'undefined'){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var el = document.createElement('div');
|
||||||
|
var prefixes = ['', 'webkit', 'moz', 'MS', 'o'];
|
||||||
|
var isSupport = prefixes.some(function(prefix){
|
||||||
|
var eventName = 'on' + prefix.toLowerCase() + 'animationend'
|
||||||
|
return eventName in el;
|
||||||
|
});
|
||||||
|
el = null;
|
||||||
|
|
||||||
|
return isSupport;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查指定元素是否已连接到文档的 DOM 树中
|
||||||
|
* @param {HTMLElement} element - 需要检查的 HTML 元素
|
||||||
|
* @returns {boolean} - 如果元素已连接到 DOM 树则返回 true,否则返回 false
|
||||||
|
*/
|
||||||
|
var isConnectedElement = function(){
|
||||||
|
if('isConnected' in Node.prototype){
|
||||||
|
return function(el){
|
||||||
|
return el.isConnected;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
return function(el){
|
||||||
|
return document.body.contains(el);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
exports(component.CONST.MOD_NAME, component);
|
exports(component.CONST.MOD_NAME, component);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue