在Vant4+Vue3+TypeScript的H5移动前端使用UnoCSS

UnoCSS 是一个 即时原子化 CSS(Atomic CSS / Utility-first CSS)引擎,类似于 Tailwind CSS 或 Windi CSS,但更轻量、灵活、性能高。本篇随笔结合项目代码介绍在Vant4+Vue3+TypeScript的H5移动前端使用UnoCSS。

UnoCSS 它的核心理念是:

  • 原子化 CSS:每一个 class 对应一条 CSS 规则,例如 p-4 就表示 padding: 1rem

  • 按需生成:只有在 HTML / JS / Vue / React / Svelte 中使用到的类,UnoCSS 才会生成对应的 CSS,避免冗余。

  • 零配置可用:开箱即用,同时支持高度自定义。

  • 极速编译:使用静态分析和即时生成技术,CSS 构建速度非常快。

官网介绍: https://unocss.dev

1、UnoCSS 核心概念

原子类(Atomic Class)
每个 class 对应一个 CSS 属性,例如:

<div class="p-4 text-red-500 bg-gray-100"></div>

对应 CSS:

div { padding: 1rem; color: #f56565; background-color: #f7fafc; }

Preset(预设)

预定义的一套 class 规则,例如:

  • presetWind3 → 类似 Tailwind 风格

  • presetAttributify → 属性化写法 <div p="4" text="red-500"></div>

  • presetIcons → 图标类自动生成

Shortcuts(快捷类)

将多个 class 合并为一个,例如:

shortcuts: {
  btn: 'px-4 py-2 rounded bg-blue-500 text-white'
}

变体(Variants)

前缀用于状态或响应式:

  • hover:bg-blue-500 → 悬停时背景蓝色

  • md:flex → 中屏及以上显示 flex 布局

  • dark:text-white → 暗黑模式下字体白色

UnoCSS = 原子化 + 按需生成 + 极速编译 + 高度可定制的 CSS 工具库

2、如何掌握UnoCSS

要熟练使用 UnoCSS,你需要掌握它背后的 原子化 CSS 规则和标识符。其实,UnoCSS 并没有发明新的 CSS 属性,它是把 CSS 属性 + 值 + 状态/变体 封装成原子类(class),所以掌握 UnoCSS 的标识,核心就是理解 CSS 属性、常用缩写和变体。我给你总结一个体系:

核心 CSS 属性标识(必会)

这些几乎是每个 UnoCSS 项目都会用到的:

类名示例对应 CSS说明
/* by 01130.hk - online tools website : 01130.hk/zh/json2cs.html */ p-4/* by 01130.hk - online tools website : 01130.hk/zh/json2cs.html */ padding: 1rem内边距
pt-2padding-top: 0.5rem上内边距
m-3margin: 0.75rem外边距
mt-1margin-top: 0.25rem上外边距
w-24width: 6rem宽度
h-32height: 8rem高度
max-w-mdmax-width: 28rem最大宽度
min-h-screenmin-height: 100vh最小高度
text-smfont-size: 0.875rem字体大小
font-boldfont-weight: 700字重
text-centertext-align: center文本对齐
leading-6line-height: 1.5rem行高
tracking-wideletter-spacing: 0.05em字间距
text-red-500color: #f56565字体颜色
bg-gray-100background-color: #f7fafc背景色
borderborder-width: 1px边框
border-gray-300border-color: #d2d6dc边框颜色
roundedborder-radius: 0.25rem圆角
rounded-lgborder-radius: 0.5rem大圆角
shadow-mdbox-shadow: 0 4px 6px -1px rgba(...)阴影

核心思路:属性缩写 + 数值/颜色/尺寸 + 状态/变体

常用状态 / 伪类变体

UnoCSS 可以直接在 class 前加状态:

前缀说明示例
hover:鼠标悬停hover:bg-blue-500
focus:获焦focus:ring-2
active:激活active:scale-95
dark:夜间模式dark:text-white
sm: / md: / lg:响应式断点md:flex

可以组合:hover:md:bg-red-500 → 在中屏及以上,鼠标悬停时背景红色

属性缩写规则(UnoCSS vs Tailwind 很类似)

  • 尺寸w-24, h-32, min-w-full

  • 间距p-4, px-2, mt-1, my-6

  • 字体text-sm, font-bold, leading-6

  • 颜色text-red-500, bg-blue-200, border-gray-300

  • 边框border, border-t, border-l-2, rounded, rounded-full

  • 阴影/动画shadow, shadow-lg, animate-bounce

  • 布局flex, grid, justify-center, items-start, gap-4

  • 定位absolute, relative, top-4, left-0

高级标识(可选)

  • 图标i-mdi-home(需要 presetIcons

  • 属性风格p="4" text="red-500"(需要 presetAttributify

  • 自定义规则 / shortcuts

shortcuts: {
  btn: 'px-4 py-2 rounded bg-blue-500 text-white'
}
使用:<button class="btn">点击</button>

3、在Vite+Vue3+TS+Vant4的H5移动前端使用UnoCSS

在Vite的移动前端项目中使用UnoCSS,和其他的操作一样,先安装在项目依赖库中

pnpm install -D unocss

一般我们还会同时使用它的预设图标处理,因此增加多两个类库。

pnpm install -D @unocss/preset-icons @iconify-json

在 uno.config.ts 中配置 presetIcons 插件。图标预设: https://unocss.dev/presets/icons

presetIcons({
  extraProperties: {'display': 'inline-block',
    'vertical-align': 'middle',
    // ...
  },
})

iconify 生态的图标都可以使用,具体可以在这里查找 Iconify(https://icones.js.org/) - 本项目推荐图标库。它是统一的图标框架,超过 150 多个图标集,和 200,000 个开源矢量图标,并且会定期更新图标。您可以在 iconify 或者 icones 中看到所有的图标集。

在VSCode下使用预设的图标集合,如下所示。

image

vite.config.ts 配置:

import Unocss from 'unocss/vite'
import { defineConfig } from 'vite'

export default defineConfig({
  plugins: [
    Unocss()
  ]
})

在 main.ts 中导入使用。

import 'virtual:uno.css'
import '@unocss/reset/tailwind-compat.css'

在界面代码中class里面使用即可

<div class="p-4 text-red-500 bg-gray-100 rounded-lg">
  Hello UnoCSS
</div>

在你的 uno.config.tsuno.config.js 中进行配置UnoCSS 即可。

import { defineConfig, presetUno } from 'unocss'
import { presetWind3 } from 'unocss/preset-wind3'

export default defineConfig({
  presets: [
    presetWind3 (),
    // ...其他 preset
  ],
})

一般来说会比这个更多一些内容。

image

而一般VSCode 安装插件UnoCSS后,

[UnoCSS](https://marketplace.visualstudio.com/items?itemName=antfu.unocss) - UnoCSS 提示插件

VSCode里面都有智能提示的,方便使用的同时也有助于了解UnoCSS的具体语法细节,如下我的项目所示。

image

生成的H5端界面效果如下所示

image 

消息详细界面中,也是统一使用了这样的样式处理方式。

<template>
  <div class="scroll-container">
    <page-header @click="goback" />
    <div class="m-2 border border-gray-300 rounded-[12px]">
      <div class="m-2 mb-2 font-bold">
        {{ article.title }}
      </div>
      <div class="m-2 flex flex-row text-xs text-gray">
        <div class="flex-grow-1">
          时间:{{ format(article.edittime) }}
        </div>
        <div class="mr-2">
          类别:{{ article.category }}
        </div>
      </div>
      <div class="m-2 mb-4 mt-2">
        <span class="line-height-loose" v-html="article.content" />
      </div>

      <van-space direction="vertical" fill class="m-4 mb-10 mt-4">
        <van-button round type="default" block @click="goback">
          返回
        </van-button>
      </van-space>
    </div>
  </div>
</template>

 下面是一些使用UnoCSS来构建界面显示的效果图,供参考。

 image   image     image

 

alt 专注于代码生成工具、.Net/Python 框架架构及软件开发,以及各种Vue.js的前端技术应用。著有Winform开发框架/混合式开发框架、微信开发框架、Bootstrap开发框架、ABP开发框架、SqlSugar开发框架、Python开发框架等框架产品。
  转载请注明出处:撰写人:伍华聪  http://www.iqidi.com 
    
先看效果: https://renmaiwang.cn/s/jkhfz Hue系列产品将具备高度的个性化定制能力,并且借助内置红、蓝、绿三原色LED的灯泡,能够混合生成1600万种不同色彩的灯光。 整个操作流程完全由安装于iPhone上的应用程序进行管理。 这一创新举措为智能照明控制领域带来了新的启示,国内相关领域的从业者也积极投身于相关研究。 鉴于Hue产品采用WiFi无线连接方式,而国内WiFi网络尚未全面覆盖,本研究选择应用更为普及的蓝牙技术,通过手机蓝牙与单片机进行数据交互,进而产生可调节占空比的PWM信号,以此来控制LED驱动电路,实现LED的调光功能以及DIY调色方案。 本文重点阐述了一种基于手机蓝牙通信的LED灯设计方案,该方案受到飞利浦Hue智能灯泡的启发,但考虑到国内WiFi网络的覆盖限制,故而选用更为通用的蓝牙技术。 以下为相关技术细节的详尽介绍:1. **智能照明控制系统**:智能照明控制系统允许用户借助手机应用程序实现远程控制照明设备,提供个性化的调光及色彩调整功能。 飞利浦Hue作为行业领先者,通过红、蓝、绿三原色LED的混合,能够呈现1600万种颜色,实现了全面的定制化体验。 2. **蓝牙通信技术**:蓝牙技术是一种低成本、短距离的无线传输方案,工作于2.4GHz ISM频段,具备即插即用和强抗干扰能力。 蓝牙协议栈由硬件层和软件层构成,提供通用访问Profile、服务发现应用Profile以及串口Profiles等丰富功能,确保不同设备间的良好互操作性。 3. **脉冲宽度调制调光**:脉冲宽度调制(PWM)是一种高效能的调光方式,通过调节脉冲宽度来控制LED的亮度。 当PWM频率超过200Hz时,人眼无法察觉明显的闪烁现象。 占空比指的...
<think>我们正在使用Vue3、Vite和Vant4来开发移动端应用,现在需要封装一个表格组件。移动端表格通常需要适应小屏幕,因此我们可能会考虑使用Vant的组件作为基础,比如使用`van-cell`来构建表格的行和列。 目标:封装一个表格组件,使其在移动端有良好的展示效果。 步骤: 1. 设计组件的props:我们需要定义表格的列(columns)和数据(data)。 2. 使用Vant的组件来构建表格的每一行和每一列。由于移动端屏幕宽度有限,表格通常采用垂直堆叠的方式(每行数据展示为一行,每一列数据在行内垂直排列)或者横向滚动的方式(保持表头固定,内容区域横向滚动)。这里我们选择横向滚动的方式,因为这样更符合传统表格的展示,同时利用移动端的触摸滑动。 但是,Vant并没有提供原生的表格组件,因此我们需要自己封装。我们可以这样设计: - 表格分为两部分:表头(thead)和表体(tbody)。 - 表头:使用一行`van-cell`来显示列名,每个列名是一个`van-cell`,然后这些`van-cell`放在一个可以横向滚动的容器内。 - 表体:每行数据也是一个横向滚动的容器,里面用多个`van-cell`来显示每个字段。 然而,考虑到移动端空间有限,另一种常见的做法是使用列表的形式展示数据,每一行数据用一个卡片,卡片内部将数据按照列名分行显示(即垂直排列)。这种形式在移动端更常见。但是用户要求的是表格组件,所以我们还是以横向展示为主。 这里我们采用横向滚动表格,因为数据列可能较多,在移动端无法在一屏内显示完全,横向滚动是常见的解决方案。 具体实现: 1. 组件结构: - 最外层一个div,设置宽度100%,溢出隐藏。 - 表头区域:一个div,设置横向滚动,内部一个div用于放置表头单元格,使用flex布局不换行。 每个表头单元格使用`van-cell`,设置固定的宽度(或者根据列定义的宽度)。 - 表体区域:同样一个div,横向滚动,内部通过循环数据生成行,每行也是一个div(使用flex布局不换行),然后每列同样使用`van-cell`,宽度与表头对应。 2. 列定义:我们可以定义每一列的宽度(可以是固定宽度,如100px,也可以是百分比,但建议固定宽度,因为横向滚动需要)。如果列数较多,固定宽度可以保证每列宽度一致。 3. 考虑到性能,我们可以使用虚拟滚动,但这里我们先实现基础表格,后续再考虑优化。 4. 由于Vant的Cell组件默认是块级元素,我们需要将其改为行内块或者使用flex布局。 我们开始编写代码: 首先,创建`ScrollTable.vue`组件。 步骤: 1. 定义props:columns(数组,每列包含title, dataIndex, width等)和data(数组,每项是一个对象,包含列中要显示的数据)。 2. 在模板中构建表头和表体。 注意:为了保持表头和表体的列对齐,每列的宽度应该保持一致。 代码示例: ```vue <template> <div class="scroll-table"> <!-- 表头 --> <div class="header-wrapper"> <div class="header-row"> <div v-for="column in columns" :key="column.dataIndex" class="header-cell" :style="{ width: column.width + &#39;px&#39; }"> {{ column.title }} </div> </div> </div> <!-- 表体 --> <div class="body-wrapper"> <div v-for="(row, index) in data" :key="index" class="body-row"> <div v-for="column in columns" :key="column.dataIndex" class="body-cell" :style="{ width: column.width + &#39;px&#39; }"> {{ row[column.dataIndex] }} </div> </div> </div> </div> </template> <script lang="ts"> import { defineComponent, PropType } from &#39;vue&#39; // 定义列的类型 interface Column { title: string; dataIndex: string; width: number; // 固定宽度,单位px } export default defineComponent({ name: &#39;ScrollTable&#39;, props: { columns: { type: Array as PropType<Column[]>, required: true }, data: { type: Array as PropType<Record<string, any>[]>, required: true } } }) </script> <style scoped> .scroll-table { width: 100%; } .header-wrapper, .body-wrapper { overflow-x: auto; /* 横向滚动 */ white-space: nowrap; /* 防止换行 */ } .header-row, .body-row { display: flex; } .header-cell, .body-cell { flex: 0 0 auto; /* 不放大不缩小,宽度固定 */ min-height: 44px; /* 最小高度 */ display: flex; align-items: center; padding: 0 10px; border-bottom: 1px solid #eee; } .header-cell { font-weight: bold; background-color: #f7f8f9; } /* 可以自定义滚动条样式(可选) */ </style> ``` 说明: - 这里我们使用flex布局来实现横向排列,每行(header-row和body-row)都是一个flex容器,每个单元格都是flex item,宽度固定。 - 表头和表体都设置了横向滚动,这样当列数超出屏幕宽度时,可以横向滚动查看。 - 注意:表头和表体的每一列宽度必须相同,所以我们通过column.width来设置,且单位是px。 但是,上面的实现中,表头和表体是分开滚动的。我们希望表头滚动时,表体也跟随滚动,反之亦然。这需要同步滚动,我们可以通过给两个滚动容器添加滚动事件监听来实现同步。 为了同步滚动,我们可以在滚动表体时,同时设置表头的滚动位置,反之亦然。但是,通常我们只希望表体滚动时表头跟着滚动(因为表头在上面,用户不会直接去滚动表头),所以我们可以只同步表体滚动到表头。 修改代码,实现表体滚动时表头同步滚动: 1. 给表头容器和表体容器分别设置ref。 2. 监听表体容器的滚动事件,在滚动时设置表头容器的滚动位置。 修改后的模板部分: ```vue <template> <div class="scroll-table"> <!-- 表头 --> <div ref="headerRef" class="header-wrapper"> <div class="header-row"> <div v-for="column in columns" :key="column.dataIndex" class="header-cell" :style="{ width: column.width + &#39;px&#39; }"> {{ column.title }} </div> </div> </div> <!-- 表体 --> <div ref="bodyRef" class="body-wrapper" @scroll="handleBodyScroll"> <div v-for="(row, index) in data" :key="index" class="body-row"> <div v-for="column in columns" :key="column.dataIndex" class="body-cell" :style="{ width: column.width + &#39;px&#39; }"> {{ row[column.dataIndex] }} </div> </div> </div> </div> </template> ``` 在script部分: ```ts import { defineComponent, PropType, ref } from &#39;vue&#39; // ... 其他代码 export default defineComponent({ // ... 其他 setup() { const headerRef = ref<HTMLElement | null>(null) const bodyRef = ref<HTMLElement | null>(null) const handleBodyScroll = (e: Event) => { if (headerRef.value) { headerRef.value.scrollLeft = (e.target as HTMLElement).scrollLeft } } return { headerRef, bodyRef, handleBodyScroll } } }) ``` 这样,当表体横向滚动时,表头也会跟着横向滚动,保持列对齐。 注意:这个表格组件比较简单,没有考虑复杂的功能(如固定列、排序、分页等),但作为一个基础表格组件,它已经能在移动端提供横向滚动的表格展示。 另外,我们使用Vant的样式作为基础,但这里没有直接使用Vant的Cell组件,因为我们需要自定义布局。如果需要,我们可以将单元格替换为`van-cell`,但是`van-cell`默认是块级元素,我们需要调整其显示方式(比如设置为inline-block)并覆盖一些样式。 如果希望使用`van-cell`,可以修改模板中的单元格部分: ```vue <van-cell v-for="column in columns" :key="column.dataIndex" class="header-cell" :style="{ width: column.width + &#39;px&#39; }" :title="column.title" /> ``` 但是注意,在表体中,我们可能需要自定义内容,而不仅仅是文本。因此,我们可以使用插槽(slot)来提供自定义内容的能力。 改进:支持自定义单元格内容 我们可以为每一列定义一个插槽,这样用户可以在使用表格组件时自定义每个单元格的渲染。 由于动态插槽在Vue3中可以使用,我们可以这样修改: 在columns的定义中,可以增加一个slotName字段,然后在表格组件的表体中,使用作用域插槽。 但为了简单,我们可以提供一个默认插槽,同时允许通过列配置的slotName来指定插槽。 修改后的表体部分: ```vue <div v-for="column in columns" :key="column.dataIndex" class="body-cell" :style="{ width: column.width + &#39;px&#39; }"> <slot v-if="column.slotName" :name="column.slotName" :row="row" :column="column"></slot> <template v-else> {{ row[column.dataIndex] }} </template> </div> ``` 这样,在父组件中,我们可以这样使用: ```vue <ScrollTable :columns="columns" :data="data"> <template #action="{ row }"> <van-button type="primary" size="mini" @click="handleAction(row)">操作</van-button> </template> </ScrollTable> ``` 其中,columns中对应的列需要设置slotName: &#39;action&#39;。 最后,考虑到移动端性能,如果数据量很大,这个表格可能会有性能问题(因为渲染了所有行)。我们可以考虑使用虚拟滚动,但虚拟滚动实现较复杂,这里不展开。 总结:我们封装了一个支持横向滚动的表格组件,支持自定义列宽和自定义单元格内容,并且实现了表头和表体的滚动同步。 注意:在实际使用中,可能还需要考虑边框、样式调整等,可以根据需要调整CSS。 以上就是一个基本的移动端表格组件的封装方法。 由于引用中提到了Vant,我们可以考虑使用Vant的一些样式来美化表格,比如使用Vant的边框样式、单元格样式等。 另外,我们还可以考虑使用Vant的Sticky组件来固定表头,这样在滚动时表头可以始终可见。但是我们的表头已经和表体一起滚动了,所以这里没有使用Sticky。如果需要表头在页面顶部固定,可以将表头用Sticky包裹,但要注意横向滚动的同步可能需要调整。 根据需求,我们可以进一步扩展功能,比如排序、筛选等,但这些都是后续可以添加的。 现在,我们可以使用这个组件来展示移动端表格了。 </think> ### 封装 Vue3 + Vite + Vant4 移动端表格组件的方法 在移动端封装表格组件时,需要考虑小屏幕适配、触摸操作优化和性能问题。以下是完整实现方案: #### 1. 基础表格组件封装(`ScrollTable.vue`) ```vue <template> <div class="scrollable-table"> <!-- 表头 --> <div class="table-header van-hairline--bottom"> <div v-for="col in columns" :key="col.key" :style="{ width: col.width }" class="header-cell" > {{ col.title }} </div> </div> <!-- 表格主体 --> <van-pull-refresh v-model="loading" @refresh="onRefresh"> <div class="table-body"> <template v-if="dataSource.length"> <div v-for="(row, index) in dataSource" :key="row.id || index" class="table-row van-hairline--bottom" @click="handleRowClick(row)" > <div v-for="col in columns" :key="col.key" :style="{ width: col.width }" class="body-cell" > <slot :name="col.slot || &#39;default&#39;" :row="row" :value="row[col.dataIndex]"> {{ row[col.dataIndex] }} </slot> </div> </div> </template> <van-empty v-else description="暂无数据" /> </div> </van-pull-refresh> <!-- 分页 --> <van-pagination v-if="pagination" v-model="currentPage" :page-count="pageCount" mode="simple" @change="handlePageChange" /> </div> </template> <script setup lang="ts"> import { ref, computed } from &#39;vue&#39; import { Empty, Pagination, PullRefresh } from &#39;vant&#39; interface Column { title: string dataIndex: string key: string width?: string slot?: string } interface Props { columns: Column[] dataSource: any[] pagination?: boolean total?: number pageSize?: number } const props = withDefaults(defineProps<Props>(), { dataSource: () => [], pagination: false, pageSize: 10 }) const emit = defineEmits([&#39;row-click&#39;, &#39;page-change&#39;, &#39;refresh&#39;]) const currentPage = ref(1) const loading = ref(false) // 计算分页 const pageCount = computed(() => { return props.pagination && props.total ? Math.ceil(props.total / props.pageSize) : 0 }) // 行点击事件 const handleRowClick = (row: any) => { emit(&#39;row-click&#39;, row) } // 分页变化 const handlePageChange = (page: number) => { currentPage.value = page emit(&#39;page-change&#39;, page) } // 下拉刷新 const onRefresh = () => { loading.value = true emit(&#39;refresh&#39;, () => { loading.value = false }) } </script> <style scoped> .scrollable-table { width: 100%; overflow: hidden; } .table-header, .table-row { display: flex; align-items: center; padding: 12px 8px; } .header-cell { font-weight: 600; font-size: 14px; color: #333; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .body-cell { font-size: 13px; color: #666; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .table-body { max-height: 60vh; overflow-y: auto; -webkit-overflow-scrolling: touch; } </style> ``` #### 2. 在项目中引入组件 ```typescript // main.ts import { createApp } from &#39;vue&#39; import App from &#39;./App.vue&#39; import Vant from &#39;vant&#39; import &#39;vant/lib/index.css&#39; const app = createApp(App) app.use(Vant) app.mount(&#39;#app&#39;) ``` #### 3. 使用示例 ```vue <template> <div class="container"> <ScrollTable :columns="columns" :data-source="tableData" :pagination="true" :total="total" :page-size="10" @row-click="handleRowClick" @page-change="fetchData" @refresh="fetchData" > <!-- 自定义状态列 --> <template #status="{ value }"> <van-tag :type="value === 1 ? &#39;success&#39; : &#39;danger&#39;"> {{ value === 1 ? &#39;启用&#39; : &#39;禁用&#39; }} </van-tag> </template> <!-- 自定义操作列 --> <template #action="{ row }"> <van-button size="mini" type="primary" @click.stop="handleEdit(row)" > 编辑 </van-button> </template> </ScrollTable> </div> </template> <script setup lang="ts"> import { ref } from &#39;vue&#39; import ScrollTable from &#39;@/components/ScrollTable.vue&#39; const columns = ref([ { title: &#39;姓名&#39;, dataIndex: &#39;name&#39;, key: &#39;name&#39;, width: &#39;25%&#39; }, { title: &#39;年龄&#39;, dataIndex: &#39;age&#39;, key: &#39;age&#39;, width: &#39;15%&#39; }, { title: &#39;状态&#39;, dataIndex: &#39;status&#39;, key: &#39;status&#39;, width: &#39;20%&#39;, slot: &#39;status&#39; }, { title: &#39;操作&#39;, key: &#39;action&#39;, width: &#39;40%&#39;, slot: &#39;action&#39; } ]) const tableData = ref([ { id: 1, name: &#39;张三&#39;, age: 28, status: 1 }, { id: 2, name: &#39;李四&#39;, age: 32, status: 0 } ]) const total = ref(20) // 行点击事件 const handleRowClick = (row: any) => { console.log(&#39;点击行:&#39;, row) } // 编辑操作 const handleEdit = (row: any) => { console.log(&#39;编辑:&#39;, row) } // 获取数据(模拟) const fetchData = (page = 1) => { console.log(&#39;加载页码:&#39;, page) // 这里调用API获取数据 } </script> <style> .container { padding: 12px; background: #f7f8fa; height: 100vh; } </style> ``` #### 4. 关键技术点说明 1. **响应式设计** - 使用百分比宽度适配不同屏幕尺寸 - 通过`overflow-y: auto`实现垂直滚动 - 添加`-webkit-overflow-scrolling: touch`优化移动端滚动体验 2. **性能优化** - 虚拟滚动支持大数据量(可通过`vue-virtual-scroller`扩展) - 使用`v-for`的`:key`确保高效渲染 - 分页加载减少DOM节点数量 3. **Vant集成** - 使用`van-pull-refresh`实现下拉刷新 - 使用`van-pagination`实现分页控制 - 使用`van-empty`处理空数据状态 4. **扩展性设计** - 通过插槽机制支持自定义单元格内容 - 支持分页、排序等扩展功能 - 暴露行点击、分页变化等事件接口 5. **移动端优化** - 触摸友好的点击区域 - 适当的内边距确保可操作性 - 简洁的视觉设计符合移动端风格 #### 5. 进阶优化建议 1. **虚拟滚动实现** ```vue // 添加虚拟滚动支持 <RecycleScroller class="table-body" :items="dataSource" :item-size="54" key-field="id" > <template v-slot="{ item: row }"> <div class="table-row">...</div> </template> </RecycleScroller> ``` 2. **列排序功能** ```typescript // 列配置增加排序支持 const columns = ref([ { title: &#39;姓名&#39;, dataIndex: &#39;name&#39;, key: &#39;name&#39;, sorter: (a, b) => a.name.localeCompare(b.name) } ]) // 排序实现 const sortData = (key, sorter) => { dataSource.value.sort(sorter) } ``` 3. **列固定功能** ```css /* 固定首列 */ .first-column { position: sticky; left: 0; z-index: 2; background: white; } ``` 这样封装的表格组件在移动端具有良好体验,支持常见功能,且易于扩展,符合 Vue3 的组合式 API 最佳实践[^3][^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值