1. 程式人生 > >Vue多種方法實現表頭、首列固定

Vue多種方法實現表頭、首列固定

有時表格太大,滾動時資訊檢視不方便,需要對錶格進行全域性表頭、首列固定,
上效果:
固定表頭首列

一、建立多個表格進行覆蓋

    思路:當頁面滾動到臨界值時,出現固定表頭、首列
    先建立一個活動表格
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            th,
            td
{ min-width: 200px; height: 50px; } #sTable { margin-top: 300px } [v-cloak]{ display: none; }
</style> </head> <body v-cloak> <!--活動的表格-->
<table id="sTable" border="1" cellspacing="0"> <thead> <tr> <th v-for="item in th">
{{item.key}}</th> </tr> </thead> <tbody> <tr v-for="item in tl"
>
<td v-for="list in item">
{{list.key}}</td> </tr> </tbody> </table> <script src="vue.js"></script> <script src="jquery.js"></script> <script> var vm = new Vue({ el: "body", data: function() { return { th: [], tl: [], temp: [], } }, methods: { //生成表格 CTable: function() { for(var i = 0; i < 10; i++) { this.th.push({ key: "head" + i }) } for(var i = 0; i < 100; i++) { for(var j = 0; j < 10; j++) { this.temp.push({ key: j + "body" + i }) } this.tl.push(this.temp) this.temp = [] } }, }, ready: function() { this.CTable(); }, }) </script> </body> </html>

再新增固定表頭:

#fHeader {
    background: lightblue;
    position: fixed;
    top: 0;
}
<!--固定表頭-->
<table border="1" id="fHeader" cellspacing="0" v-show="fixedHeader"> 
    <thead>
        <tr >
            <th v-for="item in th">{{item.key}}</th>
        </tr>
    </thead>
</table>

監控表格位置到達視窗頂部時出現固定表頭

//監控表頭位置
headerMonitor:function(){
    var self=this
    var hHeight=$("#sTable").offset().top;
    $(document).scroll(function(){
        //當滾動條達到偏移值的時候,出現固定表頭
        if($(this).scrollTop()>hHeight){
            self.fixedHeader=true
        }else{
            self.fixedHeader=false
        }

    })
}

當然需要呼叫該方法

ready: function() {
    this.CTable();
    this.headerMonitor()
},

然後新增固定首列以及固定的A1單元格

#fHeader {
    background: lightblue;
        position: fixed;
        top: 0;
        z-index: 1;
    }
    .fixedA1{
        background: lightblue;
        position: fixed;
        top: 0;
        left: 0;
        z-index:2;
    }
<!--固定A1-->
<table border="1" cellspacing="0" class="fixedA1" v-show="fixedA1">
    <thead>
        <tr>
            <th v-for="item in th" v-if="$index==0">{{item.key}}</th>
        </tr>
    </thead>
</table>
<!--固定首列-->
<table border="1" cellspacing="0" class="fixedCol" v-show="fixedCol">
    <thead>
        <tr>
            <th v-for="item in th" v-if="$index==0">{{item.key}}</th>
        </tr>
    </thead>
    <tbody>
        <tr v-for="item in tl">
            <td  v-for="list in item" v-if="$index==0">{{list.key}}</td>
        </tr>
    </tbody>
</table >

同理監控表格的位置

//監控表頭、首列位置
monitor:function(){
    var self=this
    $(document).scroll(function(){
        self.setPosition()
        //當滾動條達到左偏移值的時候,出現固定列頭
        if($(this).scrollLeft()>self.hLeft){
            self.fixedCol=true
        }else{
            self.fixedCol=false
        }
        //當滾動條達到上偏移值的時候,出現固定表頭
        if($(this).scrollTop()>self.hHeight){
            self.fixedHeader=true
        }else{
            self.fixedHeader=false
        }
        //當表格移到左上角時,出現固定的A1表格
        if($(this).scrollLeft()>self.hLeft&&$(this).scrollTop()>self.hHeight){
            self.fixedA1=true
        }else{
            self.fixedA1=false
        }
    })
},

因為表格的移動會影響表頭的位置的定位位置,因此需要將當前表格的偏移值賦給固定表頭。首列

setPosition:function(){
    $("#fHeader").css("left",this.hLeft-$(document).scrollLeft())
    $(".fixedCol").css("top",this.hHeight-$(document).scrollTop())
}

二、控制樣式實現固定表頭,首列

思路:當表格達到臨界值時,改變表頭,首列的樣式
首先實現表頭固定
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            th,
            td {
                min-width: 200px;
                height: 50px;
            }
            table {
                margin: 300px
            }
            .fHeader {
                background: lightblue;
                position: fixed;
                top: 0;
            }
            [v-cloak]{
                display: none;
            }
        </style>
    </head>
    <body v-cloak>
        <table border="1" cellspacing="0">
            <thead>
                <tr :class="{fHeader:fixedHeader}">
                    <th v-for="item in th">{{item.key}}</th>
                </tr>
            </thead>
            <tbody>
                <tr v-for="item in tl">
                    <td v-for="list in item">{{list.key}}</td>

                </tr>
            </tbody>
        </table>
        <script src="vue.js"></script>
        <script src="jquery.js"></script>
        <script>
            var vm = new Vue({
                el: "body",
                data: function() {
                    return {
                        th: [],
                        tl: [],
                        temp: [],
                        fixedHeader: false,
                    }
                },
                methods: {
                    //生成表格,程式碼相同,省略
                    CTable: function() {},
                    //監控表頭位置
                    headerMonitor:function(){
                        var self=this
                        var hHeight=$("table").offset().top;
                        $(document).scroll(function(){
                            //當滾動條達到偏移值的時候,出現固定表頭
                            if($(this).scrollTop()>hHeight){
                                self.fixedHeader=true
                            }else{
                                self.fixedHeader=false
                            }
                        })
                    }
                },
                ready: function() {
                    this.CTable();
                    this.headerMonitor()
                },
            })
        </script>
    </body>
</html>

新增固定首列

.fixedCol>:first-child{
    background: lightblue;
    position: fixed;
    z-index: 1;
    border:1px solid grey;
    left: 0;
    line-height: 50px;
}

監控表格位置

//監控表頭,首列位置
monitor:function(){
    this.setPosition()
    var self=this
    $(document).scroll(function(){
        self.setPosition();
        //當滾動條達到偏移值的時候,出現固定表頭
        if($(this).scrollTop()>self.hHeight){
            self.fixedHeader=true;
        }else{
            self.fixedHeader=false
        }
        //當滾動條達到左偏移值的時候,出現固定列頭
        if($(this).scrollLeft()>self.hLeft){
            self.fixedCol=true
        }else{
            self.fixedCol=false
        }
        //當表格移到左上角時,出現固定的A1表格
        if($(this).scrollLeft()>self.hLeft&&$(this).scrollTop()>self.hHeight){
            self.fixedA1=true
        }else{
            self.fixedA1=false
        }
    })
},

設定偏移值

//使固定表頭與列頭的偏差與當前表格的偏移值相等
setPosition:function(){
    $(".fixedHeader").css("left",this.hLeft-$(document).scrollLeft())
    for(var i=0,len=this.tl.length+1;i<len;i++){
        //因為設定了“border-collapse:collapse”,所以要加“54-1”
        $(".fixedCol>:first-child").eq(i).css("top",this.hHeight-$(document).scrollTop()+53*i)
    }
}

因為當表頭變成fixed定位時會脫離文件流,表格的第二行會被隱藏,所以需要多第二列進行寬高的拓展

/*因為fixed定位不佔位,當固定表頭出現時,有一行會補到表頭位置,即有一行跳空,將tbody的第一行行高加倍*/
.fixedHeaderGap:first-child>td{
        padding-top:54px;
    }
/*因為fixed定位不佔位,當固定列頭出現時,有一列會補到列頭位置,即有一列跳空,將tbody的第二列p設定padding*/
.fixedCol>:nth-child(2){
    padding-left: 205px;
}

當再次瀏覽器開啟時該頁面時,需要監控表格是否還達到固定表頭的臨界條件

watch:{
    //頁面初始載入時,使固定表頭與列頭的偏差與當前表格的偏移值相等
    "fixedHeader":function(){
        this.setPosition()
    },
    "fixedCol":function(){
        this.setPosition()
    },
},

三、Vue自定義指令實現滾動監聽

當使用vue時,就很少會用到Jq這麼龐大的庫,而且vue官方也不推薦操作Dom元素,因此可以自定義指令實現固定表頭,首列。本文用的是Vue.js v1.0.26,但V2.0的思路其實也一樣。
直接上程式碼
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            th,
            td {
                min-width: 200px;
                height: 50px;
            }
            #sTable {
                margin: 300px
            }
            .fixedCol{
                position: fixed;
                left: 0;
                background: lightblue;
                z-index: 1;
            }
            #fHeader {
                background: lightblue;
                position: fixed;
                top: 0;
                z-index: 1;
            }
            .fixedA1{
                background: lightblue;
                position: fixed;
                top: 0;
                left: 0;
                z-index:2;
            }
            [v-cloak]{
                display: none;
            }
        </style>
    </head>
    <body v-cloak>
        <!--固定A1-->
        <table border="1" cellspacing="0" class="fixedA1" v-show="fixedA1">
            <thead>
                <tr>
                    <th v-for="item in th" v-if="$index==0">{{item.key}}</th>
                </tr>
            </thead>
        </table>
        <!--固定列頭-->
        <table border="1" cellspacing="0" class="fixedCol" v-show="fixedCol">
            <thead>
                <tr>
                    <th v-for="item in th" v-if="$index==0">{{item.key}}</th>
                </tr>
            </thead>
            <tbody>
                <tr v-for="item in tl">
                    <td  v-for="list in item" v-if="$index==0">{{list.key}}</td>
                </tr>
            </tbody>
        </table >
        <!--固定表頭-->
        <table border="1" id="fHeader" cellspacing="0" v-show="fixedHeader"> 
            <thead>
                <tr >
                    <th v-for="item in th">{{item.key}}</th>
                </tr>
            </thead>
        </table>
        <!--活動的表格,繫結自定義指令-->
        <table id="sTable" border="1" cellspacing="0" v-scroll>
            <thead>
                <tr>
                    <th v-for="item in th">{{item.key}}</th>
                </tr>
            </thead>
            <tbody>
                <tr v-for="item in tl">
                    <td  v-for="list in item">{{list.key}}</td>
                </tr>
            </tbody>
        </table>
        <script src="vue.js"></script>
        <script>
            var vm = new Vue({
                el: "body",
                data: function() {
                    return {
                        th: [],
                        tl: [],
                        temp: [],
                        fixedCol: false,
                        fixedHeader:false,
                        fixedA1:false,
                        hLeft:0,
                        hHeight:0,
                    }
                },
                directives:{
                    scroll:{
                        bind:function(){
                            //觸發滾動監聽事件
                            window.addEventListener('scroll',function(){
                                this.vm.monitor()
                            })
                        }
                    }
                },
                methods: {
                    //生成表格
                    CTable: function() {},
                    //監控表頭、列頭位置
                    monitor:function(){
                        this.setPosition();
                        //當滾動條達到左偏移值的時候,出現固定列頭
                        if(document.body.scrollLeft>this.hLeft){
                            this.fixedCol=true;
                        }else{
                            this.fixedCol=false;
                        }
                        //當滾動條達到上偏移值的時候,出現固定表頭
                        if(document.body.scrollTop>this.hHeight){
                            this.fixedHeader=true;
                        }else{
                            this.fixedHeader=false;
                        }
                        //當表格移到左上角時,出現固定的A1表格
                        if(document.body.scrollLeft>this.hLeft&&document.body.scrollTop>this.hHeight){
                            this.fixedA1=true;
                        }else{
                            this.fixedA1=false;
                        }
                    },
                    //使固定表頭與列頭的偏差與當前表格的偏移值相等
                    setPosition:function(){
                        document.getElementById("fHeader").style.left=this.hLeft-document.body.scrollLeft+"px";
                        document.getElementsByClassName("fixedCol")[0].style.top=this.hHeight-document.body.scrollTop+"px";
                    },
                },
                ready: function() {
                    this.CTable();
                    this.hLeft=document.getElementById("sTable").offsetLeft;
                    this.hHeight=document.getElementById("sTable").offsetTop
                    this.monitor()
                },
            })
        </script>
    </body>
</html>

若想要做成自定義回撥事件,可以用eval(),

<table id="sTable" border="1" cellspacing="0" v-scroll="monitor">
directives:{
    scroll:{
        bind:function(){
            var self=this;
            //觸發滾動監聽事件
            window.addEventListener('scroll',function(){
                //觸發滾動回撥事件
                eval("self.vm."+self.expression)()
            })
        }
    }
},