first commit

This commit is contained in:
lingxiao865
2026-02-10 08:05:03 +08:00
commit c5af079d8c
1094 changed files with 97530 additions and 0 deletions

View File

@@ -0,0 +1,44 @@
:: BASE_DOC ::
## API
### Skeleton Props
name | type | default | description | required
-- | -- | -- | -- | --
custom-style | Object | - | CSS(Cascading Style Sheets) | N
animation | String | none | options: gradient/flashed/none | N
delay | Number | 0 | \- | N
loading | Boolean | true | \- | N
row-col | Array | - | Typescript`SkeletonRowCol` `type SkeletonRowCol = Array<Number \| SkeletonRowColObj \| Array<SkeletonRowColObj>>` `interface SkeletonRowColObj { width?: string; size?: string;height?: string; marginRight?: string; marginLeft?: string; margin?: string; type?: 'rect' \| 'circle' \| 'text';}`。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/skeleton/type.ts) | N
theme | String | text | options: avatar/image/text/paragraph | N
### Skeleton Slots
name | Description
-- | --
\- | \-
### Skeleton External Classes
className | Description
-- | --
t-class | \-
t-class-col | \-
t-class-row | \-
### CSS Variables
The component provides the following CSS variables, which can be used to customize styles.
Name | Default Value | Description
-- | -- | --
--td-skeleton-circle-border-radius | @skeleton-circle-border-radius | -
--td-skeleton-animation-flashed | rgba(90%, 90%, 90%, 0.3) | -
--td-skeleton-animation-gradient | rgba(0, 0, 0, 4%) | -
--td-skeleton-bg-color | @bg-color-secondarycontainer | -
--td-skeleton-circle-height | 96rpx | -
--td-skeleton-rect-border-radius | @radius-default | -
--td-skeleton-rect-height | 32rpx | -
--td-skeleton-row-spacing | @spacer-2 | -
--td-skeleton-text-border-radius | @radius-small | -
--td-skeleton-text-height | 32rpx | -

View File

@@ -0,0 +1,82 @@
---
title: Skeleton 骨架屏
description: 用于等待加载内容所展示的占位图形组合,有动态效果加载效果,减少用户等待焦虑。
spline: data
isComponent: true
---
## 引入
可在 `main.ts` 或在需要使用的页面或组件中引入。
```js
import TSkeleton from '@tdesign/uniapp/skeleton/skeleton.vue';
```
### 骨架屏类型
基础骨架屏
{{ theme }}
单元格骨架屏
{{ cell-group }}
宫格骨架屏
{{ grid }}
图文组合骨架屏
{{ image-group }}
### 组件动效
{{ animation }}
## API
### Skeleton Props
名称 | 类型 | 默认值 | 描述 | 必传
-- | -- | -- | -- | --
custom-style | Object | - | 自定义样式 | N
animation | String | none | 动画效果,有「渐变加载动画」和「闪烁加载动画」两种。值为 'none' 则表示没有动画。可选项gradient/flashed/none | N
delay | Number | 0 | 延迟显示加载效果的时间,用于防止请求速度过快引起的加载闪烁,单位:毫秒 | N
loading | Boolean | true | 是否为加载状态,如果是则显示骨架图,如果不是则显示加载完成的内容 | N
row-col | Array | - | 高级设置,用于自定义行列数量、宽度高度、间距等。【示例一】,`[1, 1, 2]` 表示输出三行骨架图,第一行一列,第二行一列,第三行两列。【示例二】,`[1, 1, { width: '100px' }]` 表示自定义第三行的宽度为 `100px`。【示例三】,`[1, 2, [{ width, height }, { width, height, marginLeft }]]` 表示第三行有两列且自定义宽度、高度、尺寸圆形或方形使用、间距、内容等。TS 类型:`SkeletonRowCol` `type SkeletonRowCol = Array<Number \| SkeletonRowColObj \| Array<SkeletonRowColObj>>` `interface SkeletonRowColObj { width?: string; size?: string;height?: string; marginRight?: string; marginLeft?: string; margin?: string; type?: 'rect' \| 'circle' \| 'text';}`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/skeleton/type.ts) | N
theme | String | text | 骨架图风格有基础、头像组合等两大类。可选项avatar/image/text/paragraph | N
### Skeleton Slots
名称 | 描述
-- | --
\- | 默认插槽,自定义内容区域内容
### Skeleton External Classes
类名 | 描述
-- | --
t-class | 根节点样式类
t-class-col | 行样式类
t-class-row | 列样式类
### CSS Variables
组件提供了下列 CSS 变量,可用于自定义样式。
名称 | 默认值 | 描述
-- | -- | --
--td-skeleton-circle-border-radius | @skeleton-circle-border-radius | -
--td-skeleton-animation-flashed | rgba(90%, 90%, 90%, 0.3) | -
--td-skeleton-animation-gradient | rgba(0, 0, 0, 4%) | -
--td-skeleton-bg-color | @bg-color-secondarycontainer | -
--td-skeleton-circle-height | 96rpx | -
--td-skeleton-rect-border-radius | @radius-default | -
--td-skeleton-rect-height | 32rpx | -
--td-skeleton-row-spacing | @spacer-2 | -
--td-skeleton-text-border-radius | @radius-small | -
--td-skeleton-text-height | 32rpx | -

View File

@@ -0,0 +1,41 @@
/* eslint-disable */
/**
* 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC
* */
import type { TdSkeletonProps } from './type';
export default {
/** 动画效果,有「渐变加载动画」和「闪烁加载动画」两种。值为 'none' 则表示没有动画 */
animation: {
type: String,
default: 'none' as TdSkeletonProps['animation'],
validator(val: TdSkeletonProps['animation']): boolean {
if (!val) return true;
return ['gradient', 'flashed', 'none'].includes(val);
},
},
/** 延迟显示加载效果的时间,用于防止请求速度过快引起的加载闪烁,单位:毫秒 */
delay: {
type: Number,
default: 0,
},
/** 是否为加载状态,如果是则显示骨架图,如果不是则显示加载完成的内容 */
loading: {
type: Boolean,
default: true,
},
/** 高级设置,用于自定义行列数量、宽度高度、间距等。【示例一】,`[1, 1, 2]` 表示输出三行骨架图,第一行一列,第二行一列,第三行两列。【示例二】,`[1, 1, { width: '100px' }]` 表示自定义第三行的宽度为 `100px`。【示例三】,`[1, 2, [{ width, height }, { width, height, marginLeft }]]` 表示第三行有两列,且自定义宽度、高度、尺寸(圆形或方形使用)、间距、内容等 */
rowCol: {
type: Array,
},
/** 骨架图风格,有基础、头像组合等两大类 */
theme: {
type: String,
default: 'text' as TdSkeletonProps['theme'],
validator(val: TdSkeletonProps['theme']): boolean {
if (!val) return true;
return ['avatar', 'image', 'text', 'paragraph'].includes(val);
},
},
};

View File

@@ -0,0 +1,77 @@
.t-skeleton {
box-sizing: border-box;
}
.t-skeleton__row {
display: flex;
margin-bottom: var(--td-skeleton-row-spacing, var(--td-spacer-2, 32rpx));
align-items: center;
justify-content: space-between;
}
.t-skeleton__row:only-child,
.t-skeleton__row:last-child {
margin-bottom: 0;
}
.t-skeleton__col {
background-color: var(--td-skeleton-bg-color, var(--td-bg-color-secondarycontainer, var(--td-gray-color-1, #f3f3f3)));
display: flex;
align-items: center;
justify-content: center;
margin-right: var(--td-spacer-2, 32rpx);
}
.t-skeleton__col:first-child:last-child,
.t-skeleton__col:last-child {
margin-right: 0;
}
.t-skeleton--type-text {
width: 100%;
height: var(--td-skeleton-text-height, 32rpx);
border-radius: var(--td-skeleton-text-border-radius, var(--td-radius-small, 6rpx));
}
.t-skeleton--type-rect {
width: 100%;
height: var(--td-skeleton-rect-height, 32rpx);
border-radius: var(--td-skeleton-rect-border-radius, var(--td-radius-default, 12rpx));
}
.t-skeleton--type-circle {
width: var(--td-skeleton-circle-height, 96rpx);
height: var(--td-skeleton-circle-height, 96rpx);
border-radius: var(--td-skeleton-circle-border-radius, var(--td-skeleton-circle-border-radius, var(--td-radius-circle, 50%)));
flex-shrink: 0;
}
.t-skeleton--animation-gradient {
position: relative;
overflow-x: hidden;
}
.t-skeleton--animation-gradient::after {
content: ' ';
position: absolute;
bottom: 0;
left: 0;
right: 0;
top: 0;
background: linear-gradient(90deg, rgba(255, 255, 255, 0), var(--td-skeleton-animation-gradient, rgba(0, 0, 0, 0.04)), rgba(255, 255, 255, 0));
animation: t-skeleton--gradient 1.5s linear 0s infinite;
}
.t-skeleton--animation-flashed {
animation: t-skeleton--flashed 2s linear 0s infinite;
}
@keyframes t-skeleton--gradient {
0% {
transform: translateX(-100%) skewX(-15deg);
}
100% {
transform: translateX(100%) skewX(-15deg);
}
}
@keyframes t-skeleton--flashed {
0% {
opacity: 1;
}
50% {
background-color: var(--td-skeleton-animation-flashed, rgba(230, 230, 230, 0.3));
opacity: 0.3;
}
100% {
opacity: 1;
}
}

View File

@@ -0,0 +1,211 @@
<template>
<view>
<view
v-if="isShow"
:style="tools._style([customStyle])"
:class="[classPrefix + ' ', tClass]"
>
<view
v-if="parsedRowCols.length"
:class="classPrefix + '__content'"
>
<view
v-for="(row, index) in parsedRowCols"
:key="index"
:class="[
classPrefix + '__row ',
tClassRow
]"
>
<view
v-for="(col, index1) in row"
:key="index1"
:class="[col.class + ' ', tClassCol]"
:style="tools._style(col.style)"
/>
</view>
</view>
</view>
<view
v-else
:class="classPrefix + '__content'"
>
<slot />
</view>
</view>
</template>
<script>
import { uniComponent } from '../common/src/index';
import { prefix } from '../common/config';
import props from './props';
import { classNames } from '../common/utils';
import { isInteger, isNumeric } from '../common/validator';
import tools from '../common/utils.wxs';
const name = `${prefix}-skeleton`;
const ThemeMap = {
avatar: [{
type: 'circle',
size: '96rpx',
}],
image: [{
type: 'rect',
size: '144rpx',
}],
text: [[{
width: '24%',
height: '32rpx',
marginRight: '32rpx',
}, {
width: '76%',
height: '32rpx',
}], 1],
paragraph: [1, 1, 1, {
width: '55%',
}],
};
export default uniComponent({
name,
options: {
styleIsolation: 'shared',
},
externalClasses: [
`${prefix}-class`,
`${prefix}-class-col`,
`${prefix}-class-row`,
],
props: {
...props,
},
data() {
return {
prefix,
classPrefix: name,
parsedRowCols: [],
isShow: false,
tools,
timer: null,
};
},
watch: {
rowCol: {
handler() {
this.init();
},
immediate: true,
},
loading: 'isShowSkeleton',
delay: 'isShowSkeleton',
},
mounted() {
this.init();
this.isShowSkeleton();
},
beforeUnMount() {
this.clearTimer();
},
methods: {
init() {
const { theme, rowCol } = this;
const rowCols = [];
if (rowCol && rowCol.length) {
rowCols.push(...rowCol);
} else {
rowCols.push(...ThemeMap[theme || 'text']);
}
const parsedRowCols = rowCols.map((item) => {
if (isInteger(item) && item >= 0) {
return new Array(item).fill({
class: this.getColItemClass({ type: 'text' }),
style: {},
});
}
if (Array.isArray(item)) {
return item.map(col => ({
...col,
class: this.getColItemClass(col),
style: this.getColItemStyle(col),
}));
}
const nItem = item;
return [
{
...nItem,
class: this.getColItemClass(nItem),
style: this.getColItemStyle(nItem),
},
];
});
this.parsedRowCols = parsedRowCols;
},
getColItemClass(obj) {
return classNames([
`${name}__col`,
`${name}--type-${obj.type || 'text'}`,
`${name}--animation-${this.animation}`,
]);
},
getColItemStyle(obj) {
const styleName = [
'width',
'height',
'marginRight',
'marginLeft',
'margin',
'size',
'background',
'backgroundColor',
'borderRadius',
];
const style = {};
styleName.forEach((name) => {
if (name in obj) {
const px = isNumeric(obj[name]) ? `${obj[name]}px` : obj[name];
if (name === 'size') {
[style.width, style.height] = [px, px];
} else {
style[name] = px;
}
}
});
return style;
},
clearTimer() {
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
}
},
isShowSkeleton() {
this.clearTimer();
const { loading, delay } = this;
if (!loading || delay === 0) {
this.isShow = loading;
return;
}
this.timer = setTimeout(() => {
this.isShow = this.loading;
}, delay);
},
},
});
</script>
<style scoped>
@import './skeleton.css';
</style>

View File

@@ -0,0 +1,44 @@
/* eslint-disable */
/**
* 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC
* */
export interface TdSkeletonProps {
/**
* 动画效果,有「渐变加载动画」和「闪烁加载动画」两种。值为 'none' 则表示没有动画
* @default none
*/
animation?: 'gradient' | 'flashed' | 'none';
/**
* 延迟显示加载效果的时间,用于防止请求速度过快引起的加载闪烁,单位:毫秒
* @default 0
*/
delay?: number;
/**
* 是否为加载状态,如果是则显示骨架图,如果不是则显示加载完成的内容
* @default true
*/
loading?: boolean;
/**
* 高级设置,用于自定义行列数量、宽度高度、间距等。【示例一】,`[1, 1, 2]` 表示输出三行骨架图,第一行一列,第二行一列,第三行两列。【示例二】,`[1, 1, { width: '100px' }]` 表示自定义第三行的宽度为 `100px`。【示例三】,`[1, 2, [{ width, height }, { width, height, marginLeft }]]` 表示第三行有两列,且自定义宽度、高度、尺寸(圆形或方形使用)、间距、内容等
*/
rowCol?: SkeletonRowCol;
/**
* 骨架图风格,有基础、头像组合等两大类
* @default text
*/
theme?: 'avatar' | 'image' | 'text' | 'paragraph';
}
export type SkeletonRowCol = Array<Number | SkeletonRowColObj | Array<SkeletonRowColObj>>;
export interface SkeletonRowColObj {
width?: string;
size?: string;
height?: string;
marginRight?: string;
marginLeft?: string;
margin?: string;
type?: 'rect' | 'circle' | 'text';
}