寫(xiě)在前面
本文主要介紹關(guān)于JS
或Vue
中如何進(jìn)行表頭,列固定,可以根據(jù)實(shí)際應(yīng)用場(chǎng)景應(yīng)用于原生
,Vue
,移動(dòng)端
,小程序
中
實(shí)際效果展示:
對(duì)于列的固定,table
中有對(duì)應(yīng)的方法,但是如果列和表頭都要固定,只能通過(guò)其他方式實(shí)現(xiàn),如果您找到了更好的自身方法,還請(qǐng)斧正
思路概述
表頭,列頭,表格本身,這三個(gè)內(nèi)容被分為了三塊元素,將這三個(gè)內(nèi)容進(jìn)行抽離,并且通過(guò)定位和大盒子的包裹進(jìn)行樣式管理。
【當(dāng)要進(jìn)行滾動(dòng)時(shí),只要對(duì)滾動(dòng)事件進(jìn)行綁定,讓表頭和列頭顯示對(duì)應(yīng)的內(nèi)容就完成了滾動(dòng)的操作
】
下面有Vue
組件的和JavaScript
原生的代碼,可以直接運(yùn)行查看邏輯和效果
具體實(shí)現(xiàn)
整體代碼,可以直接創(chuàng)建組件,將代碼復(fù)制到組件中使用
,在App
中引用運(yùn)行【基于vue3+ts+less
實(shí)現(xiàn),其他版本會(huì)在后面給出修改思路】【最下面也提供了原生寫(xiě)法】
<!--
~ Time:2022/8/9 13:06 29
~ Name:fixmeTable.vue
~ Path:src/components/table
~ ProjectName:element-plus
~ Author:charlatan
~
~ Il n'ya qu'un héro?sme au monde :
~ c'est de voir le monde tel qu'il est et de l'aimer.
-->
<script lang="ts" setup>
import { ref } from 'vue'
const row = 20
const column = 30
let top = ref('0px')
let left = ref('0px')
const Scroll = (event: Event) => {
top.value = -event.target.scrollTop + 'px'
left.value = -event.target.scrollLeft + 'px'
}
</script>
<template>
<h3>
列頭表頭固定table
</h3>
<hr>
<!-- 表格-->
<div class="table">
<!-- 表頭-->
<div class="rowHeader">
<table class="rowHeader-table">
<tr>
<td class="td" v-for="(item,index) in row" :key="index">
{{ item }}
</td>
</tr>
</table>
</div>
<!-- 列頭-->
<div class="columnHeader">
<table class="columnHeader-table">
<tr v-for="(RootItem,index) in column" :key="index">
<td class="td">
{{ String.fromCharCode(RootItem + 64) }}
</td>
</tr>
</table>
</div>
<!-- 表格-->
<div class="tableBody" @scroll="Scroll($event)">
<table class="tableBody-table">
<tr v-for="(RootItem,index) in column" :key="index">
<td
class="td" v-for="(item,index) in row" :key="index">
{{ item + String.fromCharCode(RootItem + 64) }}
</td>
</tr>
</table>
</div>
</div>
</template>
<style scoped lang="less">
.table {
border: 1px solid red;
padding: 1rem;
border-radius: 1rem;
position: absolute;
left: 200px;
top: 100px;
width: 300px;
height: 300px;
// 表頭
.rowHeader {
position: relative;
width: 260px;
max-width: 300px;
overflow: hidden;
left: 30px;
.rowHeader-table {
position: relative;
left: v-bind(left);
width: fit-content;
}
}
// 列頭
.columnHeader {
position: relative;
max-height: 300px;
overflow: hidden;
width: 30px;
top: 3px;
.columnHeader-table {
position: relative;
top: v-bind(top)
}
}
// 表格本體
.tableBody {
width: 265px;
height: 300px;
position: absolute;
top: 55px;
left: 50px;
overflow: auto;
}
// 表格元素
tr {
width: fit-content;
white-space: normal;
display: flex;
.td {
display: block;
width: 30px;
height: 30px;
text-align: center;
line-height: 30px;
}
}
}
</style>
-
html
部分:主要進(jìn)行框架的設(shè)計(jì),這里表頭,列頭,表格本體分為三份<template> <h3> 列頭表頭固定table </h3> <hr> <!-- 表格--> <div class="table"> <!-- 表頭--> <div class="rowHeader"> <table class="rowHeader-table"> <tr> <td class="td" v-for="(item,index) in row" :key="index"> {{ item }} </td> </tr> </table> </div> <!-- 列頭--> <div class="columnHeader"> <table class="columnHeader-table"> <tr v-for="(RootItem,index) in column" :key="index"> <td class="td"> {{ String.fromCharCode(RootItem + 64) }} </td> </tr> </table> </div> <!-- 表格--> <div class="tableBody" @scroll="Scroll($event)"> <table class="tableBody-table"> <tr v-for="(RootItem,index) in column" :key="index"> <td class="td" v-for="(item,index) in row" :key="index"> {{ item + String.fromCharCode(RootItem + 64) }} </td> </tr> </table> </div> </div> </template>
內(nèi)容分為了三部分,這三部分將相互獨(dú)立,通過(guò)樣式的調(diào)節(jié)將三部分內(nèi)容進(jìn)行統(tǒng)一的管理。
這里使用的是
table
進(jìn)行了內(nèi)容的填充,因?yàn)楸眍^和列頭是單獨(dú)的元素,所以可以使用其他內(nèi)容如div
等,通過(guò)樣式上的和交互上的進(jìn)行協(xié)調(diào)統(tǒng)一,這里不在贅述 -
樣式上的內(nèi)容,因?yàn)橹饕枪δ?,這里樣式使用
less
進(jìn)行簡(jiǎn)單繪制<style scoped lang="less"> .table { border: 1px solid red; padding: 1rem; border-radius: 1rem; position: absolute; left: 200px; top: 100px; width: 300px; height: 300px; // 表頭 .rowHeader { position: relative; width: 260px; max-width: 300px; overflow: hidden; left: 30px; .rowHeader-table { position: relative; left: v-bind(left); width: fit-content; } } // 列頭 .columnHeader { position: relative; max-height: 300px; overflow: hidden; width: 30px; top: 3px; .columnHeader-table { position: relative; top: v-bind(top) } } // 表格本體 .tableBody { width: 265px; height: 300px; position: absolute; top: 55px; left: 50px; overflow: auto; } // 表格元素 tr { width: fit-content; white-space: normal; display: flex; .td { display: block; width: 30px; height: 30px; text-align: center; line-height: 30px; } } } </style>
內(nèi)容上和定義的結(jié)構(gòu)進(jìn)行統(tǒng)一調(diào)節(jié),這里需要主要的是:因?yàn)楸砀竦膶挾群捅眍^的寬度對(duì)應(yīng),表格的高度和列頭的高度固定,所以建議在定義時(shí)考慮好對(duì)應(yīng)的寬高對(duì)應(yīng)關(guān)系,方便調(diào)節(jié)
在定義好表頭和列頭時(shí),對(duì)與展示的部分通過(guò)外部的
div
進(jìn)行定位的調(diào)節(jié)進(jìn)行展示,內(nèi)部的表格部分通過(guò)寬度的固定來(lái)達(dá)到樣式統(tǒng)一,使用相對(duì)定位來(lái)完成展示內(nèi)容的切換內(nèi)部使用了Vue3提供的
v-bind
,如果你使用的時(shí)vue2或其他內(nèi)容請(qǐng)更換為內(nèi)聯(lián)樣式或其他方式v-bind
為Vue3中提供,主要是將綁定的內(nèi)容轉(zhuǎn)換為自定義標(biāo)簽使用,具體介紹可以看我的另一篇文章:Vue3新屬性 — v-bind in css,里面有用法和原理的詳細(xì)介紹 -
邏輯部分:主要為內(nèi)部的真正的表格綁定了滾動(dòng)的監(jiān)聽(tīng),
<script lang="ts" setup> import { ref } from 'vue' // 定義行和列 const row = 20 const column = 30 // 將內(nèi)容進(jìn)行響應(yīng)式定義 let top = ref('0px') let left = ref('0px') // 綁定對(duì)應(yīng)的監(jiān)聽(tīng)事件 const Scroll = (event: Event) => { top.value = -event.target.scrollTop + 'px' left.value = -event.target.scrollLeft + 'px' } </script>
這里使用的動(dòng)態(tài)數(shù)據(jù)在
v-bind
中進(jìn)行,這里直接修改即可
其他環(huán)境中要修改的內(nèi)容
這里對(duì)常見(jiàn)問(wèn)題進(jìn)行解決,如果沒(méi)有匹配,請(qǐng)?jiān)u論或找其他方式解決
-
原生JavaScript中使用
:如果你完全沒(méi)有使用過(guò)Vue
,上面的代碼我也改成了原生的版本,邏輯一樣,這里就只放代碼不做介紹了直接創(chuàng)建文件復(fù)制使用
<!-- ~ Time:2022/8/12 9:02 36 ~ Name:test1.html ~ Path: ~ ProjectName:element-plus ~ Author:charlatan ~ ~ Il n'ya qu'un héro?sme au monde : ~ c'est de voir le monde tel qu'il est et de l'aimer. --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta content="IE=edge" http-equiv="X-UA-Compatible"> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"> <title>Title</title> <style> * { margin: 0; padding: 0; list-style: none; font: 500 15px YouYuan; text-decoration: none; } li { cursor: pointer; position: relative; } /*-------以上為默認(rèn)設(shè)置(The above is the default setting)--------*/ .table { border: 1px solid red; padding: 1rem; border-radius: 1rem; position: absolute; left: 200px; top: 100px; width: 300px; height: 300px; } .rowHeader { position: relative; width: 260px; max-width: 300px; overflow: hidden; left: 30px; } .rowHeader-table { position: relative; left: 0; width: fit-content; } .columnHeader { position: relative; max-height: 270px; overflow: hidden; width: 30px; top: 3px; } .columnHeader-table { position: relative; top: 0; } .tableBody { width: 265px; height: 270px; position: absolute; top: 55px; left: 50px; overflow: auto; } tr { width: fit-content; white-space: normal; display: flex; } .td { display: block; width: 30px; height: 30px; text-align: center; line-height: 30px; } </style> </head> <body> <div class="table"> <!-- 表頭--> <div class="rowHeader"> <table class="rowHeader-table"> <tr id="rowHeader-table-tr"></tr> </table> </div> <!-- 列頭--> <div class="columnHeader"> <table class="columnHeader-table" id="columnHeader-table-tr"></table> </div> <!-- 表格--> <div class="tableBody" id="scroll"> <table class="tableBody-table" id="tableBody-table-tr"></table> </div> </div> </body> <script> // 定義行和列 const row = 30 const column = 30 // 獲取表頭 let rowHeard = document.getElementById('rowHeader-table-tr') // 創(chuàng)建表頭元素 for (let i = 0, len = row; i < len; i++) { // 獲取元素 let td = document.createElement('td') // 添加樣式 td.classList.add('td') // 添加內(nèi)容 let testNode = document.createTextNode(i) td.appendChild(testNode) // 將表頭放置到指定位置 rowHeard.appendChild(td) } // 創(chuàng)建表頭元素 let columnHeard = document.getElementById('columnHeader-table-tr') // 創(chuàng)建元素 for (let i = 0, len = column; i < len; i++) { let tr = document.createElement('tr') let td = document.createElement('td') td.classList.add('td') td.appendChild(document.createTextNode(String.fromCharCode(i + 64))) tr.appendChild(td) columnHeard.appendChild(tr) } // 創(chuàng)建表格元素 let table = document.getElementById('tableBody-table-tr') for (let i = 0, len = column; i < len; i++) { let tr = document.createElement('tr') for (let j = 0, len = row; j < len; j++) { let td = document.createElement('td') td.classList.add('td') td.appendChild(document.createTextNode(i + String.fromCharCode(j + 64))) tr.appendChild(td) } table.appendChild(tr) } // 獲取表頭和列頭滾動(dòng)元素 let row_heard = document.getElementsByClassName('rowHeader-table')[0] let column_heard = document.getElementsByClassName('columnHeader-table')[0] // 綁定滾動(dòng)時(shí)間 let scroll = document.getElementById('scroll') scroll.onscroll = function (event) { row_heard.style.left = -event.target.scrollLeft + 'px' column_heard.style.top = -event.target.scrollTop + 'px' } </script> </html>
主要通過(guò)的是JS的元素創(chuàng)建然后將元素添加至對(duì)應(yīng)的內(nèi)容中,然后進(jìn)行事件的綁定,從而完成整體邏輯
-
React
和小程序中
,二者都是可以進(jìn)行數(shù)據(jù)的綁定,元素的循環(huán)處理更加方法,小程序中沒(méi)有鼠標(biāo),可能要更換為手指滑動(dòng)操作,對(duì)于這個(gè)邏輯相同,綁定元素的移動(dòng)距離
,從而讓表頭和列頭跟隨移動(dòng)從而達(dá)到同步的效果和目的文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-487760.html
本文僅代表本人粗鄙的拙見(jiàn),如果有疏忽和紕漏,還請(qǐng)大佬斧正
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-487760.html
到了這里,關(guān)于JavaScript和Vue中實(shí)現(xiàn)表格(table)固定表頭和首列【提供Vue和原生代碼】的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!