HTML网页里的Tabs的意义是什么?

其实可以完全不存在 ul->div 1对1的关系。其实是点按一个按钮,更改部分位置的html内容

静态Tabs

内容直接保存在 响应的 div HTML 代码中。

动态Tabs

如果使用AJAX或者其他异步加载技术,动态的获取 tab 下的内容。

可选解决方案

1. Bootstrap

静态完整案例

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8" />
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
	<title>
		test
	</title>
	<!-- Bootstrap -->
	<link href="//cdn.bootcss.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
	<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
	<script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
	<!-- Include all compiled plugins (below), or include individual files as needed -->
	<script src="//cdn.bootcss.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
	<!-- End Bootstrap -->
</head>

<body>
	<div>
		<!-- Nav tabs -->
		<ul class="nav nav-tabs" role="tablist">
			<li role="presentation" class="active"><a href="#home" data-toggle="tab" >Home</a></li>
			<li role="presentation"><a href="#profile" data-toggle="tab" >Profile</a></li>
			<li role="presentation"><a href="#messages" data-toggle="tab" >Messages</a></li>
			<li role="presentation"><a href="#settings" data-toggle="tab" >Settings</a></li>
		</ul>

		<!-- Tab panes -->
		<div class="tab-content">
			<div role="tabpanel" class="tab-pane active" id="home">...home</div>
			<div role="tabpanel" class="tab-pane" id="profile">...profile</div>
			<div role="tabpanel" class="tab-pane" id="messages">...messages</div>
			<div role="tabpanel" class="tab-pane" id="settings">...setting</div>
		</div>
	</div>
</body>

</html>

优势

动态实例

<div class="row">
    <!-- Nav tabs -->
    <div class="nav-tabslist">
        <ul class="nav nav-pills nav-stacked col-lg-2" role="tablist">
            <li role="presentation" class=""><a href="#orders" data-toggle="tab">订单</a></li>
            <li role="presentation"><a href="#updates" data-toggle="tab">更新</a></li>
            <li role="presentation"><a href="#settings" data-toggle="tab">设置</a></li>
        </ul>

    </div>

    <!-- Tab panes -->
    <div class="tab-content col-lg-10">
        <div role="tabpanel" class="tab-pane" id="orders"></div>
        <div role="tabpanel" class="tab-pane" id="updates">...updates</div>
        <div role="tabpanel" class="tab-pane" id="settings">...setting</div>
    </div>
    
    <script>
        $(function(){
            $('.nav-pills a[href=\"#orders\"]').click(function(){
            <!-- 使用获取JSON -->
                getJSONorders(location.search.substring("?proj_id=".length),$('#orders'));
            })
            
        })
    </script>
    
</div>

对应的JSON获取函数实例(这是一个获取指定产品的所有订单并列表的函数):

var getJSONorders = function (proj_id, jq) {
    url = '/project-orders?proj_id=' + proj_id;
    var jqxhr = $.ajax(url, {
        dataType: 'json'
    }).done(function (json) {
        var orders = JSON.parse(json);
        jq.get(0).innerHTML = "<h2 id=\"h2\" class=\"project-panel-title\">订单列表</h2>"
        +"<div class='table-responsive'>"
        +"<table class='table table-striped table hover'><tr><th>#</th><th>用户ID</th><th>选项</th><th>金额</th><th>支付方式</th><th>状态</th><th>备注</th></tr>";
        
        orders.forEach(function(order,index){
            
            var tr = document.createElement('tr');
            tr.innerHTML = "<td>"+(index+1)+"</td>"
            +"<td>"+order.user_id.substring(18)+"</td>"
            +"<td>"+ ("#"+order.rw_id+": "+order.details.substring(0,5)+"..."+order.details.substring(order.details.length-5)) +"</td>"
            +"<td> ¥"+ order.rw_amout +"</td>"
            +"<td>"+ order.payment +"</td>"
            +"<td>"+ order.status +"</td>"
            +"<td>"+ (order.note || "无") +"</td>";
            
            jq.find("tbody").append(tr);
            
        })
        
    }).fail(function (xhr, status) {
        console.log(xhr.status + " " + status);
    })
}

问题

<!-- 注意放在所有异步加载函数的下面 -->
<script>
    $(function(){
        // tab() 显示该tab click() 执行绑定的异步函数。因此本行应在所有异步设置之后(.click(func) 之后)
        $('.nav-pills a[href=\"'+window.location.hash+"\"]").tab('show').click();
        
        // 当#tab发生变化时的反应
        window.onhashchange = function(){
            $('.nav-tabs a[href=\"'+window.location.hash+"\"]").tab('show');
        };
    })
</script>

2. JQuery-ui

静态完整案例

<html lang="en">
<head>
    <meta charset="utf-8">
    <title>jQuery UI Tabs - Default functionality</title>
    <script src="//code.jquery.com/jquery-1.10.2.js"></script>
    <script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
    <!-- 注意,需要手动初始化 -->
    <script>
        $(function() {
            $( "#tabs" ).tabs();
        });
    </script>
</head>
<body>
 
<div id="tabs">
    <ul>
        <li><a href="#tabs-1">Nunc tincidunt</a></li>
        <li><a href="#tabs-2">Proin dolor</a></li>
        <li><a href="#tabs-3">Aenean lacinia</a></li>
    </ul>
    <div id="tabs-1">
        tab1
    </div>
    <div id="tabs-2">
        tab2
    </div>
    <div id="tabs-3">
        tab3
    </div>
</div>
 
</body>
</html>

优势

动态完整实例

<html lang="en">
<head>
	<meta charset="utf-8">
	<title>jQuery UI Tabs - Content via Ajax</title>
	<script src="//code.jquery.com/jquery-1.10.2.js"></script>
	<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
	<script>
		$(function() {
			$( "#tabs" ).tabs({
			beforeLoad: function( event, ui ) {
				ui.jqXHR.fail(function() {
				ui.panel.html(
					"Couldn't load this tab. We'll try to fix this as soon as possible. " +
					"If this wouldn't be a demo." );
				});
			}
			});
		});
	</script>
</head>

<body>

	<div id="tabs">
		<ul>
			<li><a href="#tabs-1">Preloaded</a></li>
			
			<li><a href="https://jqueryui.com/resources/demos/tabs/ajax/content1.html">Tab 1</a></li>
			<li><a href="https://jqueryui.com/resources/demos/tabs/ajax/content2.html">Tab 2</a></li>
			<li><a href="https://jqueryui.com/resources/demos/tabs/ajax/content3-slow.php">Tab 3 (slow)</a></li>
			<li><a href="https://jqueryui.com/resources/demos/tabs/ajax/content4-broken.php">Tab 4 (broken)</a></li>
		</ul>
		<div id="tabs-1">
			static contents
		</div>
	</div>

</body>
</html>

效果

问题

对于应用Bootstrap的栅格系统的网页,如果需要让 tabs 和 tab-panel(content) 通过 col-- 来定义宽度:

<div class="container profile">
        <div id="profile-row" class="row">
            <div id="tabs" class="profile-menu col-md-2 col-lg-2 col-sm-2">
                <ul class="nav nav-pills nav-stacked">
                    <li role="presentation" class="active"><a href="/back-history">支持过的项目</a></li>
                    <li role="presentation"><a href="/created">创立的项目</a></li>
                </ul>
            </div>
        </div>
    </div>

$ui.tab 载入的panel是载入直接在div#tabs下的,如果需要把tabsstylepanelstyle应用Bootstrap的栅格系统,需要:

把结构从:

div.row>div#tabs>div.ui-tabs-panel

改为

div.row>         div.ui-tabs-panel

即将div.ui-tabs-panel提升到和div#tabs同一层,互为兄弟,这样一来才能正确处理bootstrap的col的栅格(例如tab.col-3, panel.col-9)

我的解决方案

$(function(){
    // 使用 jquery-ui 操作tabs
    $( "#tabs" ).tabs({
        // 在tab.panel载入完成后:
        load: function(event,ui){
            
            // 调整Bootstrap的按钮active颜色根据所需调整
            $('#tabs li').removeClass('active')
            ui.tab.addClass('active');
            
            // 每次clone都会append在其下面,删除 row>panel 的元素,
            $('#profile-row>div.ui-tabs-panel>div.profile-panel').remove();
            
            
            // 将载入的panel直接clone一个挂到所需要的位置
            $('#profile-row').append(ui.panel.clone());

        },        
    });
});

其中遇到了一个问题:

tab在原位置删除,并clone在新位置的过程中会现在原位置显示出来。 我想不闪那么一下,但是以下这些函数都没用

load: function(event,ui){
    ui.panel.hide();
    // 最后再显示
    $('#profile-row').append(ui.panel.clone().show());
},
beforeActivate:function(event,ui){
    ui.newPanel.hide();
},
beforeLoad:function(event,ui){
    ui.panel.hide();
},
create: function(event,ui){
    ui.panel.hide();
}

同样也失败的思路:使用 $ui 提供的 Events 来移动 oldPanel 和 NewPanel(通过append移动)。 但是元素一旦移开该ui-tabs-panel不会再次生成。调用oldPanel只会报错。

最后我使用css解决。

因此,使用这个方案同时还需要注意设置:

#tabs .profile-panel{
    display: none;
}

Bootstrap 和 JQuery-ui 对于Tab实现的对比


参考

You can activate individual tabs in several ways:

$('#myTabs a[href="#profile"]').tab('show') // Select tab by name
$('#myTabs a:first').tab('show') // Select first tab
$('#myTabs a:last').tab('show') // Select last tab
$('#myTabs li:eq(2) a').tab('show') // Select third tab (0-indexed)