feat(tabs): 增强若干功能

pull/2680/head
贤心 2025-05-13 00:19:59 +08:00
parent 7138198645
commit 1b9557cdd8
4 changed files with 149 additions and 105 deletions

View File

@ -89,13 +89,12 @@ layui.use(function() {
title: 'New Tab '+ n, // 此处加 n 仅为演示区分,实际应用不需要 title: 'New Tab '+ n, // 此处加 n 仅为演示区分,实际应用不需要
content: 'New Tab Content '+ n, content: 'New Tab Content '+ n,
id: 'new-'+ n, id: 'new-'+ n,
aaa: 'attr-'+ n, // 自定义属性,其中 aaa 可任意命名 done: function(data) {
done: function(params) { console.log(data); // 查看返回的参数
console.log(params); // 查看返回的参数
// 给新标签头添加上下文菜单 // 给新标签头添加上下文菜单
dropdown.render($.extend({}, dropdownInst.config, { dropdown.render($.extend({}, dropdownInst.config, {
elem: params.thisHeaderItem // 当前标签头元素 elem: data.headerItem // 新标签头元素 --- headerItem 为 2.11.2 新增
})); }));
} }
}, opts); }, opts);

View File

@ -122,6 +122,12 @@ tabs.render({
tabs.add('test', { tabs.add('test', {
title: 'New Tab 1', title: 'New Tab 1',
content: 'New Tab Content 1', content: 'New Tab Content 1',
done: function(data) {
console.log(data); // 标签相关数据
// 为新标签头添加任意属性
data.headerItem.attr('lay-tips', '111');
}
}); });
``` ```
@ -202,10 +208,10 @@ console.log(data);
{ {
options, // 标签配置信息 options, // 标签配置信息
container, // 标签容器的相关元素 container, // 标签容器的相关元素
thisHeaderItem, // 当前标签头部项 thisHeaderItem, // 当前活动标签头部项
thisBodyItem, // 当前标签内容项 thisBodyItem, // 当前活动标签内容项
index, // 当前标签索引 index, // 当前活动标签索引
length, // 当前标签数 length, // 标签数
} }
``` ```
@ -228,12 +234,13 @@ var headerItem = tabs.getHeaderItem('test', 'abc'); // 获取 lay-id="abc" 的
`tabs.getBodyItem(id, index)` `tabs.getBodyItem(id, index)`
- 参数 `id` : 组件的实例 ID - 参数 `id` : 组件的实例 ID
- 参数 `index` : 标签索引 - 参数 `index` : 标签索引或标签的 `lay-id` 属性值 <sup>2.11.2+</sup>
该方法用于获取标签内容项元素。 该方法用于获取标签内容项元素。
```js ```js
var bodyItem = tabs.getBodyItem('test', 3); // 获取索引为 3 的标签内容项元素 var bodyItem = tabs.getBodyItem('test', 3); // 获取索引为 3 的标签内容项元素
var bodyItem = tabs.getBodyItem('test', 'abc'); // 获取 lay-id="abc" 的标签内容项元素
``` ```
<h3 id="refresh" class="ws-anchor ws-bold">刷新标签视图</h3> <h3 id="refresh" class="ws-anchor ws-bold">刷新标签视图</h3>

View File

@ -167,27 +167,40 @@
<script src="../src/layui.js"></script> <script src="../src/layui.js"></script>
<script> <script>
layui.use(function() { layui.use(function() {
var $ = layui.$;
var tabs = layui.tabs var tabs = layui.tabs
var util = layui.util; var util = layui.util;
var layer = layui.layer; var layer = layui.layer;
var dropdown = layui.dropdown; var dropdown = layui.dropdown;
// 自定义事件 // 新增随机标签
util.on({ var addTabs = function(opts) {
add: function(){
var n = Math.random()*1000 | 0; // 演示标记 var n = Math.random()*1000 | 0; // 演示标记
opts = $.extend({
//添加标签
tabs.add('demoTabs1', {
title: 'New Tab '+ n, // 此处加 n 仅为演示区分,实际应用不需要 title: 'New Tab '+ n, // 此处加 n 仅为演示区分,实际应用不需要
content: 'New Tab Content '+ n, content: 'New Tab Content '+ n,
id: 'new-'+ n, id: 'new-'+ n,
aaa: 'attr-'+ n, // 自定义属性,其中 aaa 可任意命名 // active: false, // 是否设为活动标签
// mode: 'curr', done: function(data) {
done: function(params) { console.log(data); // 查看返回的参数
console.log(params);
// 为新标签头添加任意属性 --- 2.11.2+
data.headerItem.attr('lay-tips', 'tip-'+ n);
// 给新标签头添加上下文菜单
dropdown.render($.extend({}, dropdownInst.config, {
elem: data.headerItem // 新标签头元素
}));
} }
}); }, opts);
// 添加标签到最后
tabs.add('demoTabs1', opts);
}
// 自定义事件
util.on({
add: function(){
addTabs();
} }
}); });
@ -226,30 +239,47 @@
}); });
// 为标签头添加上下文菜单 // 为标签头添加上下文菜单
dropdown.render({ var dropdownInst = dropdown.render({
elem: '#demoTabs1 .layui-tabs-header>li', elem: '#demoTabs1 .layui-tabs-header>li',
trigger: 'contextmenu', trigger: 'contextmenu',
data: [{ data: [{
title: '关闭', title: '在右侧新增标签页',
type: 'this' action: 'add',
}, { mode: 'after'
title: '关闭其他标签页',
type: 'other'
}, {
title: '关闭右侧标签页',
type: 'right'
}, { }, {
type: '-' type: '-'
}, {
title: '关闭',
action: 'close',
mode: 'this',
}, {
title: '关闭其他标签页',
action: 'close',
mode: 'other'
}, {
title: '关闭右侧标签页',
action: 'close',
mode: 'right'
}, { }, {
title: '关闭所有标签页', title: '关闭所有标签页',
type: 'all' action: 'close',
mode: 'all'
}], }],
click: function(data, othis, event) { click: function(data, othis, event) {
var index = this.elem.index(); var index = this.elem.index(); // 获取活动标签索引
if (data.type === 'this') { // 新增标签操作
if (data.action === 'add') {
// 在当前活动标签右侧新增标签页
addTabs({
mode: data.mode,
index: index
});
} else if(data.action === 'close') { // 关闭标签操作
if (data.mode === 'this') {
tabs.close('demoTabs1', index); // 关闭当前标签 tabs.close('demoTabs1', index); // 关闭当前标签
} else { } else {
tabs.closeMult('demoTabs1', data.type, index); // 批量关闭标签 tabs.closeMult('demoTabs1', data.mode, index); // 批量关闭标签
}
} }
} }
}); });
@ -258,7 +288,7 @@
tabs.render({ tabs.render({
elem: '#demoTabs2', elem: '#demoTabs2',
header: [ header: [
{ title: 'Tab1' }, { title: 'Tab1', closable: false },
{ title: 'Tab2' }, { title: 'Tab2' },
{ title: 'Tab3' } { title: 'Tab3' }
], ],
@ -267,9 +297,9 @@
{ content: 'Tab content 2' }, { content: 'Tab content 2' },
{ content: 'Tab content 3' } { content: 'Tab content 3' }
], ],
// index: 1, //初始选中项 // index: 1, // 初始选中项
// className: 'layui-tabs-card', // className: 'layui-tabs-card',
// closable: true closable: true
}); });

View File

@ -183,6 +183,7 @@ layui.define('component', function(exports) {
var container = that.getContainer(); var container = that.getContainer();
var newHeaderItem = that.renderHeaderItem(opts); var newHeaderItem = that.renderHeaderItem(opts);
var newBodyItem = that.renderBodyItem(opts); var newBodyItem = that.renderBodyItem(opts);
var data = that.data();
// 选项默认值 // 选项默认值
opts = $.extend({ opts = $.extend({
@ -191,7 +192,6 @@ layui.define('component', function(exports) {
// 插入方式 // 插入方式
if (/(before|after)/.test(opts.mode)) { // 在活动标签前后插入 if (/(before|after)/.test(opts.mode)) { // 在活动标签前后插入
var data = that.data();
var hasOwnIndex = opts.hasOwnProperty('index'); var hasOwnIndex = opts.hasOwnProperty('index');
var headerItem = hasOwnIndex ? that.findHeaderItem(opts.index) : data.thisHeaderItem; var headerItem = hasOwnIndex ? that.findHeaderItem(opts.index) : data.thisHeaderItem;
var bodyItem = hasOwnIndex ? that.findBodyItem(opts.index) : data.thisHeaderItem; var bodyItem = hasOwnIndex ? that.findBodyItem(opts.index) : data.thisHeaderItem;
@ -214,8 +214,12 @@ layui.define('component', function(exports) {
} }
// 回调 // 回调
var params = that.data(); typeof opts.done === 'function' && opts.done(
typeof opts.done === 'function' && opts.done(params); $.extend(data, {
headerItem: newHeaderItem,
bodyItem: newBodyItem
})
);
}; };
/** /**
@ -238,7 +242,7 @@ layui.define('component', function(exports) {
} }
// 当前标签相关数据 // 当前标签相关数据
var params = that.data(); var data = that.data();
// 标签关闭前的事件。若非强制关闭,可则根据事件的返回结果决定是否关闭 // 标签关闭前的事件。若非强制关闭,可则根据事件的返回结果决定是否关闭
if (!force) { if (!force) {
@ -246,7 +250,7 @@ layui.define('component', function(exports) {
thisHeaderItem[0], thisHeaderItem[0],
component.CONST.MOD_NAME, component.CONST.MOD_NAME,
'beforeClose('+ options.id +')', 'beforeClose('+ options.id +')',
$.extend(params, { $.extend(data, {
index: thisHeaderItem.index() index: thisHeaderItem.index()
}) })
); );
@ -273,14 +277,14 @@ layui.define('component', function(exports) {
that.roll('auto', index); that.roll('auto', index);
// 获取当前标签相关数据 // 获取当前标签相关数据
var params = that.data(); var data = that.data();
// 标签关闭后的事件 // 标签关闭后的事件
layui.event.call( layui.event.call(
params.thisHeaderItem[0], data.thisHeaderItem[0],
component.CONST.MOD_NAME, component.CONST.MOD_NAME,
'afterClose('+ options.id +')', 'afterClose('+ options.id +')',
params data
); );
}; };
@ -339,14 +343,14 @@ layui.define('component', function(exports) {
that.roll('auto'); that.roll('auto');
// 回调 // 回调
var params = that.data(); var data = that.data();
// 标签关闭后的事件 // 标签关闭后的事件
layui.event.call( layui.event.call(
params.thisHeaderItem[0], data.thisHeaderItem[0],
component.CONST.MOD_NAME, component.CONST.MOD_NAME,
'afterClose('+ options.id +')', 'afterClose('+ options.id +')',
params data
); );
}; };
@ -361,7 +365,7 @@ layui.define('component', function(exports) {
var that = this; var that = this;
var options = that.config; var options = that.config;
var index = thisHeaderItem.index(); var index = thisHeaderItem.attr('lay-id') || thisHeaderItem.index();
var thatA = thisHeaderItem.find('a'); var thatA = thisHeaderItem.find('a');
// 是否存在跳转链接 // 是否存在跳转链接
var isLink = typeof thatA.attr('href') === 'string' && thatA.attr('target') === '_blank'; var isLink = typeof thatA.attr('href') === 'string' && thatA.attr('target') === '_blank';
@ -374,7 +378,7 @@ layui.define('component', function(exports) {
} }
// 当前标签相关数据 // 当前标签相关数据
var params = that.data(); var data = that.data();
// 标签关闭前的事件。若非强制关闭,可则根据事件的返回结果决定是否关闭 // 标签关闭前的事件。若非强制关闭,可则根据事件的返回结果决定是否关闭
if (!force) { if (!force) {
@ -382,10 +386,10 @@ layui.define('component', function(exports) {
thisHeaderItem[0], thisHeaderItem[0],
component.CONST.MOD_NAME, component.CONST.MOD_NAME,
'beforeChange('+ options.id +')', 'beforeChange('+ options.id +')',
$.extend(params, { $.extend(data, {
from: { from: {
index: params.index, index: data.index,
headerItem: params.thisHeaderItem headerItem: data.thisHeaderItem
}, },
to: { to: {
index: thisHeaderItem.index(), index: thisHeaderItem.index(),
@ -411,14 +415,14 @@ layui.define('component', function(exports) {
that.roll('auto', index); that.roll('auto', index);
// 重新获取标签相关数据 // 重新获取标签相关数据
var params = that.data(); var data = that.data();
// 标签切换后的事件 // 标签切换后的事件
layui.event.call( layui.event.call(
params.thisHeaderItem[0], data.thisHeaderItem[0],
component.CONST.MOD_NAME, component.CONST.MOD_NAME,
'afterChange('+ options.id +')', 'afterChange('+ options.id +')',
params data
); );
}; };
@ -431,17 +435,8 @@ layui.define('component', function(exports) {
var options = that.config; var options = that.config;
var headerItem = $(opts.headerItem || options.headerItem || '<li></li>'); var headerItem = $(opts.headerItem || options.headerItem || '<li></li>');
headerItem.html(opts.title || 'New Tab'); headerItem.html(opts.title || 'New Tab').attr('lay-id', opts.id);
that.appendClose(headerItem, opts); // 追加标签关闭元素
// 追加属性
layui.each(opts, function(key, value){
if(/^(title|content|mode|done)$/.test(key)) return;
headerItem.attr('lay-'+ key, value);
});
// 追加标签关闭元素
that.appendClose(headerItem, opts);
return headerItem; return headerItem;
}; };
@ -450,11 +445,11 @@ layui.define('component', function(exports) {
* @param {Object} opts - 标签项配置信息 * @param {Object} opts - 标签项配置信息
*/ */
Class.prototype.renderBodyItem = function(opts) { Class.prototype.renderBodyItem = function(opts) {
var that = this var that = this;
var options = that.config var options = that.config;
var bodyItem = $(opts.bodyItem || options.bodyItem || '<div class="'+ component.CONST.ITEM +'"></div>'); var bodyItem = $(opts.bodyItem || options.bodyItem || '<div class="'+ component.CONST.ITEM +'"></div>');
bodyItem.html(opts.content || ''); bodyItem.html(opts.content || '').attr('lay-id', opts.id);
return bodyItem; return bodyItem;
}; };
@ -472,7 +467,7 @@ layui.define('component', function(exports) {
opts = opts || {}; opts = opts || {};
// 不可关闭项 // 不可关闭项
if (opts.closable === 'false' || headerItem.attr('lay-closable') === 'false') { if (opts.closable == false || headerItem.attr('lay-closable') === 'false') {
return; return;
} }
@ -493,16 +488,15 @@ layui.define('component', function(exports) {
var options = that.config; var options = that.config;
var container = that.getContainer(); var container = that.getContainer();
container.header.items.each(function() {
var $this = $(this);
// 是否开启关闭 // 是否开启关闭
if (options.closable) { if (options.closable) {
container.header.items.each(function() { that.appendClose($this);
that.appendClose($(this));
});
} else { } else {
container.header.items.each(function() { $this.find('.'+ component.CONST.CLOSE).remove();
$(this).find('.'+ component.CONST.CLOSE).remove();
});
} }
});
}; };
/** /**
@ -652,25 +646,36 @@ layui.define('component', function(exports) {
}; };
/** /**
* 根据 id index 获取相关标签头部项 * 获取标签头部项
* @param {number|string} index - 标签索引或 id * @param {number|string} index - 标签索引或 lay-id
*/ */
Class.prototype.findHeaderItem = function(index) { Class.prototype.findHeaderItem = function(index) {
if(!( var container = this.getContainer();
typeof index === 'number' var headerItems = container.header.items;
|| (typeof index === 'string' && index) var headerItem = headerItems.filter('[lay-id="'+ index +'"]');
)) return; return headerItem[0] ? headerItem : headerItems.eq(index);
var headerItems = this.getContainer().header.items;
var item = headerItems.filter('[lay-id="'+ index +'"]');
return item[0] ? item : headerItems.eq(index);
}; };
/** /**
* 根据 index 获取相关标签内容项 * 获取标签内容项
* @param {number} index - 标签索引 * @param {number} index - 标签索引lay-id
*/ */
Class.prototype.findBodyItem = function(index) { Class.prototype.findBodyItem = function(index) {
return this.getContainer().body.items.eq(index); var container = this.getContainer();
var bodyItems = container.body.items;
var bodyItem = bodyItems.filter('[lay-id="'+ index +'"]');
return bodyItem[0] ? bodyItem : function() {
// 若未匹配到 lay-id 对应内容项,则继续匹配对应头部项
var headerItems = container.header.items;
var headerItem = headerItems.filter('[lay-id="'+ index +'"]');
if (headerItem[0]) {
index = headerItem.index();
}
return bodyItems.eq(index);
}();
}; };
/** /**
@ -687,11 +692,11 @@ layui.define('component', function(exports) {
return { return {
options: options, // 标签配置信息 options: options, // 标签配置信息
container: container, // 标签容器的相关元素 container: container, // 标签容器的相关元素
thisHeaderItem: thisHeaderItem, // 当前标签头部项 thisHeaderItem: thisHeaderItem, // 当前活动标签头部项
thisBodyItem: that.findBodyItem(index), // 当前标签内容项 thisBodyItem: that.findBodyItem(index), // 当前活动标签内容项
index: index, // 当前标签索引 index: index, // 当前活动标签索引
length: container.header.items.length // 当前标签数 length: container.header.items.length // 标签数
} };
}; };
// 扩展组件接口 // 扩展组件接口
@ -715,8 +720,11 @@ layui.define('component', function(exports) {
*/ */
close: function(id, index, force) { close: function(id, index, force) {
var that = component.getInst(id); var that = component.getInst(id);
if(!that) return; if (!that) return;
if(index === undefined) index = that.data().index; // index 若不传,则表示关闭当前标签 // index 若不传,则表示关闭当前标签
if (index === undefined) {
index = that.data().index;
}
that.close(that.findHeaderItem(index), force); that.close(that.findHeaderItem(index), force);
}, },
@ -755,7 +763,7 @@ layui.define('component', function(exports) {
/** /**
* 获取标签指定头部项 * 获取标签指定头部项
* @param {string} id - 渲染时的实例 ID * @param {string} id - 渲染时的实例 ID
* @param {number} index - 标签索引 * @param {number} index - 标签索引lay-id
* @returns * @returns
*/ */
getHeaderItem: function(id, index) { getHeaderItem: function(id, index) {
@ -767,7 +775,7 @@ layui.define('component', function(exports) {
/** /**
* 获取标签指定内容项 * 获取标签指定内容项
* @param {string} id - 渲染时的实例 ID * @param {string} id - 渲染时的实例 ID
* @param {number} index - 标签索引 * @param {number} index - 标签索引lay-id
* @returns * @returns
*/ */
getBodyItem: function(id, index) { getBodyItem: function(id, index) {