vue2,vue3移动端实现表格固定和首列固定(代码片段)

twinkle||cll twinkle||cll     2022-11-30     380

关键词:

好久都没有写文章了,上个月业务繁忙,事情比较多,最近在做移动端中发现了一个好玩的事情,那就是移动端中实现表格,固定列有哪些方法:

1. position: sticky

粘性布局,这个属性也可以实现行和列的固定,在pc端上没有啥问题,但是在手机端上会抖动。

使用注意事项:

要求父级不能够使用overflow:auto,否则不生效。

牛刀小试

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Test</title>
  <style>
    *,
    body,
    html 
      margin: 0;
      padding: 0;
      box-sizing: border-box;
      height: 100%;
      width: 100%;
    

    .condition 
      height: 50px;
      background-color: rgb(19, 13, 13);
      color: #fff;
      font-size: 2em;
      text-align: center;
    

    .table-container 
      width: 100%;
      height: calc(100% - 50px);
      overflow: auto;
    

    table 
      border-collapse: collapse;
    

    th,
    td 
      padding: 5px;
      text-align: center;
      border: 1px solid #999;
      min-width: 100px;
    

    th 
      background-color: #333;
      color: #fff;
      position: sticky;
      top: 0px;
    

    td:first-child 
      background-color: #333;
      color: #fff;
      position: sticky;
      left: 0px;
    

    th:first-child 
      position: sticky;
      left: 0px;
      top: 0px;
      z-index: 10;
    
  </style>
  <script src="https://cdn.staticfile.org/vue/2.5.17-beta.0/vue.min.js"></script>
  <script>
    document.addEventListener("DOMContentLoaded", function () 
      let t = new Vue( el: "#app" );
    );
  </script>
</head>

<body>
  <div id="app">
    <!-- 其他东西 -->
    <div class="condition">条件查询</div>
    <div class="table-container">
      <table>
        <thead>
          <tr>
            <th v-for="(n,i) of 50">字段 i+1</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="(n,i) of 100">
            <td v-for="(m,j) of 50">j+1</td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>

</body>

</html>

pc端的效果如下:

pc端的效果咋们都可以接收,虽然会有点看起来不舒服。

移动端效果

这啥呀,还抖动的,对于真机的测试,安卓会抖动,但是苹果机型不会抖动。这种肯定是不行的,打开ele的table看到人家的表格蛮不错的,那就学习下。

2.多表格实现固定

思路,在ele中,固定是有多个表格来的,所以咋也来搞多个表格。首先将表格分成左右两部分,左边第一列在上下滑动是header部分需要固定;右边第一行在左右滑动时firstRow和header部分也需要是固定的。可将这几个划分区域分别用table填充,滑动tableBody时保持firstRow和firstCol的同步滑动即可。

看看效果图

这回总不会抖动了吧,为了方便大家学习,我就把我的这个组件贡献出来。让有需要的同学使用,vue3都出来了这么久,肯定用vue3了哇!

<script lang='ts' setup>
import  computed, Ref, ref  from 'vue'

const props = defineProps<

  // 传我表头,表头的列数,需要和tableData每一个对象里的属性值一样
  headerData:  title: string, props: string [],
  // 表格数据
  tableData:  [key: string]: any [],
  // 表格高度
  tableScrollHeight: number
>()

const tableContainer: Ref<HTMLDivElement | null> = ref(null);
const firstRowLayer: Ref<HTMLDivElement | null> = ref(null);
const firstColLayer: Ref<HTMLDivElement | null> = ref(null);

// 第一列数据
const firstCol = computed(() => props.tableData.map(p => 
  const pArr = Object.keys(p);
  return p[pArr[0]]
))
// 第一个表头,第一列
const header = computed(() => props.headerData[0].title);
// 第一行
const firstRow = computed(() => 
  const rows: string[] = [];
  props.headerData.forEach((f, i) => 
    if (i !== 0) 
      rows.push(f.title)
    
  )
  return rows;
)



// 表格内容行
const tableBodyRows = computed(() => 
  let arr:  [key: string]: any [] = [];
  props.tableData.forEach((f, index) => 
    // 接下来排除第一列
    let res:  [key: string]: any  = ;
    for (const key in f) 
      if (Object.prototype.hasOwnProperty.call(f, key)) 
        if (key !== props.headerData[0].title) 
          res[key] = f[key]
        
      
    
    arr.push(res)
  )
  return arr
)
// 表格内容列
const tableBodyCols = computed(() => 
  let arr:  title: string, props: string [] = []
  props.headerData.forEach((f, i) => 
    if (i !== 0) 
      arr.push(f)
    
  )
  return arr;
)


// table滚动
const tableScroll = () => 
  // 首行固定
  firstRowLayer.value!.scrollLeft = tableContainer.value!.scrollLeft;
  // 首列固定
  firstColLayer.value!.scrollTop = tableContainer.value!.scrollTop;

</script>
<template>
  <div class="content-table">
    <template v-if="props.tableData.length > 0">
      <div class="left-div">
        <div class="left-div1">
          <table>
            <tr>
              <th> header </th>
            </tr>
          </table>
        </div>
        <div
          ref="firstColLayer"
          class="left-div2"
          :style=" height: `calc(100vh - $tableScrollHeightpx` "
        >
          <table class="left-table2">
            <tr v-for="(col, index) in firstCol" :key="index">
              <td> col </td>
            </tr>
          </table>
        </div>
      </div>
      <div class="right-div">
        <div ref="firstRowLayer" class="right-div1">
          <table class="right-table1" :style=" width: (firstRow.length - 1) * 100 + 'px' ">
            <tr>
              <th class="first-row-style" v-for="(row, index) in firstRow" :key="index"> row </th>
            </tr>
          </table>
        </div>
        <div
          ref="tableContainer"
          class="right-div2"
          :style=" height: `calc(100vh - $tableScrollHeightpx` "
          @scroll="tableScroll()"
        >
          <table class="right-table2" :style=" width: (firstRow.length - 1) * 100 + 'px' ">
            <tr v-for="(body,index) in tableBodyRows" :key="index">
              <td v-for="(col, i) in tableBodyCols" :key="col.props + i"> body[col.props] </td>
            </tr>
          </table>
        </div>
      </div>
    </template>
    <template v-else>
      <div class="empty-content">
        <table
          cellspacing="0"
          :style=" width: (headerData.length - 1) * 100 + 'px', height: '10rem', overflow: 'auto' "
        >
          <thead class="table-header">
            <tr>
              <th v-for="(item,index) in props.headerData" :key="item.title"> item.title </th>
            </tr>
          </thead>
          
          <van-empty class="empty-res" description="空空如也!" />
        </table>
      </div>
    </template>
  </div>
</template>

<style lang="scss" scoped>
.content-table 
  box-sizing: border-box;
  overflow-x: hidden;

table 
  border-collapse: collapse;
  margin: 0 auto;
  width: 100%;
  border-spacing: 0;
  font-size: 13px;

th 
  word-break: break-all;
  word-wrap: break-word;
  height: 40px;
  width: 100px;
  vertical-align: middle;
  text-align: center;
  border-left: 1px solid #999;
  background: #d9d9d9;
  box-sizing: border-box;

td 
  word-break: break-all;
  word-wrap: break-word;
  width: 100px;
  text-align: center;
  vertical-align: middle;
  line-height: 30px;
  border-left: 1px solid #999;
  box-sizing: border-box;

tr 
  border-top: 1px solid #999;
  box-sizing: border-box;

.left-div 
  width: 100px;
  float: left;

.left-div1 
  width: 100%;

.left-div2 
  width: 100%;
  overflow: hidden;

.left-table2 
  margin-bottom: 4px;

.right-div 
  float: left;
  width: calc(100vw - 100px);
  margin-left: -1px;

.right-div1 
  width: 100%;
  overflow: hidden;

  .first-row-style 
    box-sizing: border-box;
  

.right-div2 
  width: 100%;
  overflow: auto;


.right-table2 
  overflow: hidden;

table tr:nth-child(odd) 
  background: rgba(255, 255, 255, 0.3);

table tr:nth-child(even) 
  background: rgba(153, 153, 153, 0.3);

.empty-content 
  width: 100%;
  overflow: auto;

</style>

上个月自己也用vue3写了个前台的管理系统,有需要的可以看看哦!http://ruoyi-doc.chenliangliang.top/

vue中实现table的首行首列固定

参考技术A移动端需要表格展示数据时,需要滑动表格实现展示更多数据的目的,固定表格的首行和首列可在查看数据时更加直观。首先将表格分成左右两部分,左边第一列在上下滑动是header部分需要固定;右边第一行在左右滑... 查看详情

saiku如何固定查询结果table的表头和首列

...维度不清楚,得来回拖动滚动条才行,所以同事提出想要固定“表头”和“首列”。在网上找了一些现成的插件使用后效果都不理想,所以决定自己动手,丰衣足食。我的思路来自:http://www.cnblogs.com 查看详情

利用css的sticky特性实现固定首列其他列滚动

1<!doctypehtml>2<html>3<head>4<metacharset="utf-8">5<metaname="viewport"content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no"/>6<linkrel="s 查看详情

移动端固定头部和固定左边第一列的实现方案(vue中实现demo)

最近移动端做一份报表,需要左右滚动时,固定左边部分;上下滚动时,固定头部部分。代码在Vue中简单实现主要思路是:a.左边部分滚动,实时修改右边部分的滚动条高度b.头部和内容部分都设置固定高度,当内容部分内容高度... 查看详情

实现移动端顶部与底部固定,内容区优化的效果

实现顶部与底部固定的效果十分容易,且很多人都会选择用这个方式,就是顶部position:fixed,底部也position:fixed。实现的效果就像下面两张图,container区域是布满整个屏幕的,且滚动条也是滚动在整个屏幕中,调内容区时只能调... 查看详情

京东开源的轻量级移动端vue2vue3组件库

...VIP会员」圈子,每日更新,精彩不断。京东风格的轻量级移动端Vue2、Vue3组件库,支持一套代码生成H5和小程序。特性70+高质量组件(3.0持续开发中),覆盖移动端主流场景支持小程序开发基于京东App10.0视觉规范支持按需引用详... 查看详情

css让表格第一列和第一行固定

用css让表格左右移动滚动条的时候第一列固定,上下移动滚动条的时候第一行固定。并且浏览器兼容,麻烦提供全网页代码。参考技术A给你提供个思路:第一行为一行多列的表格;第一列为一列多行的表格;剩下就是一个表格... 查看详情

移动端背景无法固定

在移动端制作固定背景时(利用fixed)会出现滚动条滚动时,背景图会跟着滚动,;解决办法就是给body加个伪元素。body:before{content:‘‘;position:fixed;z-index:-1;top:0;right:0;bottom:0;left:0;background:url(...)center0no-repeat;background-size:cover;} 查看详情

移动端背景固定

body:before{    content:‘‘;    position:fixed;    z-index:-1;    top:0;    right:0;    查看详情

移动端使用绝对定位来模拟固定定位(代码片段)

一、原因  固定定位是参考布局视口做定位的,而在移动端,存在布局视口、视觉视口、理想视口,如果适配方案使用不正确,很容易造成布局错误。二、案例1,有问题版本,在唤起虚拟键盘的时候,布局错乱了。<!DOCTYPEht... 查看详情

移动端:移动端页面布局(代码片段)

移动端页面布局一、水平居中行内元素   text-align:center;块级元素1/*可以采取绝对定位的方式实现*/2.center3width:960px;4position:absolute;5left:50%;(25%)6margin-left:-480px;7二、自适应块级元素水平居中前面介绍的块级元素居中要... 查看详情

移动端尾部和头部固定

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><metahttp-equiv="X-UA-Compatible"content="ie 查看详情

vue移动端开发列表左边固定右边可以左右滑动上下滑动同步?

参考技术A可以请采纳 查看详情

excel如何冻结首行或首列及首行首列同时冻结

...里的冻结首列即可。效果如下:拖动水平滚动条冻结首行和首列:冻结首行和首列,应先选中B2单元格(即首行和首列的交点),然后在菜单栏选择视图菜单,再选择冻结窗格下拉三角里的冻结拆分窗 查看详情

web移动端实现自适应缩放界面的方法汇总(代码片段)

方案一:设置tranform/scale首先设置内容固定宽度、自动高度(以下举例)width:375px;height:auto; 通过获取窗口的宽度与固定宽度相除,获得缩放比例constscaleValue=window.innerWidth/375 在html层,添加一段script:<scriptdangerouslySetInner... 查看详情

excel2017如何同时冻结首行首列不滚动

工具Excel2017方法步骤例如要冻结图中表格的首行首列。先点击选中图中所示的左上角首行和首列交叉处的单元格。再点击菜单栏中的“视图”并点击“冻结窗口”。点击冻结窗口中的“冻结拆分窗格”。点击冻结拆分窗格后,表... 查看详情

vue项目中h5移动端中通过flex布局实现首尾固定,中间滚动(借鉴)

html中<divclass="flexLayoutr"><divclass="div_head"></div><divclass="div_content">中间区域</div><divclass="div_foot"></div></div>css中*margin:0;padding:0;.flexLayoutdisplay:flex;display:-webkit-flex;min-height:100vh;flex-direction:column;.div_head... 查看详情

实现固定页眉和滚动,页脚和移动问题

】实现固定页眉和滚动,页脚和移动问题【英文标题】:Materializefixedheaderandscroll,issuewithfooterandmobile【发布时间】:2019-12-1810:16:01【问题描述】:我有以下具体化表:<divclass="row"><divclass="cols12m12l12"><divid="table"class="cardc... 查看详情