@tdesign/uniapp 常见问题

675 阅读4分钟

1. 开始

罗列下 @tdesign/uniapp 中的常见问题,持续更新。

2. FAQ

2.1. setup 语法糖下函数式调用 Toast 等组件时如何传递 context

最简单的方式是在页面下预埋,这时根本不需要传递 context

<!-- 页面级别组件: xx.vue -->
<template>
 <div>
    ...
    <t-toast />
  </div>
</template>

2.2. Icon 太大怎么办

可以参考这篇文章,使用这个插件进行解决。

2.3. HBuilderX 中运行到内置浏览器时报错 Unexpected token .

报错如下:

这是 HBuilderX 自己的问题,参考这里

可以运行到 Chrome 中,或者使用 CLI 模式。

2.4. Vue2 下的适配

参考这篇文章

2.5. 报错 Failed to load font

微信开发者工具报错

[渲染层网络层错误] Failed to load font https://tdesign.gtimg.com/icon/0.4.1/fonts/t.woff
net::ERR_CACHE_MISS
(env: macOS,mp,2.01.2510270; lib: 3.14.2)

原因:微信开发者工具的 bug,忽略即可。

参考:wx.loadFontFace 文档

2.6. Input 组件内容抖动

小程序下,在 Popup 或 Dialog 等组件中,Input 组件中内容可能会抖动。

原因:本质是小程序自己的问题,可以设置组件的 transition:none; 禁用动画,或者在 Popup/Dialog 组件中,延迟显示 Input 组件。

参考:

  1. issue#3078
  2. issue#2674
  3. issue#489

之前:

之后:

2.7. 插槽类型报错

报错如下:

Property 'description' does not exist on type '{}'.

原因:tsconfig.jsoncompilerOptions.moduleResolution 配置了 node 等字段,未识别到 @tdesign/uniapp 中的 exports

解决办法:修改 tsconfig.jsoncompilerOptions.moduleResolutionbundler。可参考 tdesign-uniapp-starter

2.8. PC 浏览器环境下的拖动

PC 环境下,可以通过加载 touch-emulator 脚本来适配。

脚本地址: tdesign.gtimg.com/js/touch-em…, 你可以放到自己的 CDN 上。

2.9. Indexes 组件滑动问题

Indexes 组件依赖 onPageScroll,在小程序、APP-PLUS 等平台下,动态监听 onPageScroll 不生效,需要业务自己在页面中监听,下面给出最佳实践之一。

// 页面 Vue 文件下,引入组件库提供的监听方法
// 该方法内部会通过 event-bus,传递参数给对应的组件
import { handlePageScroll } from 'tdesign-uniapp/mixins/page-scroll';

// Vue3
defineOptions({
  onPageScroll(e) {
    handlePageScroll(e);
  },
});

// Vue2
export default {
  onPageScroll(e) {
    handlePageScroll(e);
  },
}

2.10. H5 端横滑组件导致页面上下抖动

swipe-cell 等需要横向手势的组件,在 H5 端左右滑动时,浏览器默认会同时触发纵向滚动判定,导致页面跟着上下抖动。

解决方案:在组件根节点上加一行 CSS,告诉浏览器只处理纵向手势,横向交给组件自己消费。

// 全局或父组件样式中(注意非 scoped 或加 :deep)
:deep(.t-swipe-cell) {
  touch-action: pan-y;
}

说明:

  • touch-action: pan-y 表示元素只允许浏览器接管纵向滚动,横向 touch 事件由 JS 处理,从而消除横滑抖动
  • 该属性是浏览器原生 CSS,仅 H5 端生效,小程序 / nvue 端会自动忽略,无副作用
  • 同理也可以用在其他自定义横滑组件上(如 swiper 容器、轮播 tab 等)

2.11. styleIsolation: 'shared' 的配置说明

微信、QQ 等小程序的自定义组件默认开启样式隔离(isolated),父组件的 :deep() 选择器无法穿透到子组件的 shadow-root 内部,因此当 tdesign-uniapp 组件被当作非页面级组件使用时,必须显式将其 styleIsolation 改为 shared,让外部 t-class / :deep() 写下来的样式能够命中组件内部节点。

在 Vue 3 <script setup> 语法糖下,使用 defineOptions 声明:

<script setup lang="ts">
defineOptions({
  options: {
    styleIsolation: 'shared',
  },
});
</script>

在 Options API 下,则直接挂在组件配置上:

export default {
  options: {
    styleIsolation: 'shared',
  },
};

需要注意:

  • 该配置只对小程序端(微信、QQ、百度等)生效,H5 / App 平台会自动忽略,无需做平台条件编译
  • 仅在非页面级组件(即被其他组件以自定义组件形式引入时)才需要声明,页面级组件的样式默认对其内部使用的 TDesign 组件可见,无需额外配置;
  • 配置后,外层通过 t-class:deep(.t-xxx) 写入的样式才会生效,否则在小程序端会出现"H5 正常但小程序不生效"的现象。

2.12. :deep() 在小程序端不生效的常见写法

在 uniapp 项目中,H5 平台下 <style> 默认会被加上 scoped。如果直接在顶层裸写 :deep(.xxx),编译产物会是这样的形式:

.data-v-7c5535e6 .navbar {
  padding: 20px;
}

该选择器在 H5 下能命中元素,但在微信小程序的 shadow-root 结构下匹配不到组件内部节点,因此样式不会生效。

正确的写法有两种(推荐第一种,与 uniapp H5 默认开启 scoped 的行为保持一致):

<!-- ✅ 推荐:保留 scoped,并嵌套在一个上层类名下 -->
<style lang="less" scoped>
  .app-page {
    :deep(.navbar) {
      padding: 20px;
    }
  }
</style>
<!-- ✅ 可选:不加 scoped,直接使用 :deep() -->
<style lang="less">
  :deep(.navbar) {
    padding: 20px;
  }
</style>

简而言之:要么不加 scoped,要么加了 scoped 就必须在外层包一层类名嵌套,避免编译出 [data-v-xxx] .navbar 这种无法穿透小程序 shadow-root 的选择器。