diff --git a/devui/skeleton/index.ts b/devui/skeleton/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..1e40f962128b694d836dcc4c61b4aa505a32ec10 --- /dev/null +++ b/devui/skeleton/index.ts @@ -0,0 +1,18 @@ +import type { App } from 'vue' +import Skeleton from './src/skeleton' + +Skeleton.install = function(app: App): void { + app.component(Skeleton.name, Skeleton) +} + +export { Skeleton } + +export default { + title: 'Skeleton 骨架屏', + category: '数据展示', + status: undefined, // TODO: 组件若开发完成则填入"已完成",并删除该注释 + install(app: App): void { + + app.use(Skeleton as any) + } +} diff --git a/devui/skeleton/src/skeleton-types.ts b/devui/skeleton/src/skeleton-types.ts new file mode 100644 index 0000000000000000000000000000000000000000..5774b4917b85cf5c7337e5aaa04ce1adbe7fcd89 --- /dev/null +++ b/devui/skeleton/src/skeleton-types.ts @@ -0,0 +1,22 @@ +import type { ExtractPropTypes } from 'vue' + +export const skeletonProps = { + row: { + type: Number || String, + default: 0 + }, + animate:{ + type: Boolean, + default: true + }, + loading:{ + type: Boolean, + default: true + }, + avatar:{ + type: Boolean, + default: false + } +} as const + +export type SkeletonProps = ExtractPropTypes diff --git a/devui/skeleton/src/skeleton.scss b/devui/skeleton/src/skeleton.scss new file mode 100644 index 0000000000000000000000000000000000000000..f273c771aba0975ec36a64d455a8c19cfc2dfcc2 --- /dev/null +++ b/devui/skeleton/src/skeleton.scss @@ -0,0 +1,58 @@ +.devui-skeleton { + display: flex; + justify-content: space-between; + .devui-skeleton__avatar { + display: none; + .avatar { + width: 40px; + height: 40px; + background-color: #ccc; + border-radius: 50%; + } + } + .is-shown { + flex: 1; + display: flex; + justify-content: center; + } + .devui-skeleton__item__group { + flex: 7; + .devui-skeleton__item { + width: 100%; + height: 16px; + background-color: #ccc; + display: inline-block; + border-radius: 4px; + } + .devui-skeleton__item:first-child { + width: 33%; + } + .devui-skeleton__item:last-child { + width: 61%; + } + } +} + +.devui-skeleton-animated > .devui-skeleton__avatar > .avatar, +.devui-skeleton-animated > .devui-skeleton__item__group > .devui-skeleton__item { + background-color: #ccc; + background: linear-gradient( + 100deg, + rgba(255, 255, 255, 0) 40%, + rgba(255, 255, 255, 0.5) 50%, + rgba(255, 255, 255, 0) 60% + ) + #ccc; + background-size: 200% 100%; + background-position-x: 180%; + animation: 2s loading ease-in-out infinite; +} +.devui-skeleton-animated > .devui-skeleton__avatar > .avatar { + animation-delay: 0.1s; +} + +@keyframes loading { + to { + background-position-x: -20%; + } +} diff --git a/devui/skeleton/src/skeleton.tsx b/devui/skeleton/src/skeleton.tsx new file mode 100644 index 0000000000000000000000000000000000000000..6076a06390c89b73ce3fdea37b2e62698d1df664 --- /dev/null +++ b/devui/skeleton/src/skeleton.tsx @@ -0,0 +1,32 @@ +import './skeleton.scss' + +import { defineComponent } from 'vue' +import { skeletonProps, SkeletonProps } from './skeleton-types' + +export default defineComponent({ + name: 'DSkeleton', + props: skeletonProps, + setup(props: SkeletonProps, ctx) { + const { slots } = ctx; + let arr = [] + for (let index = 0; index < props.row; index++) { + arr.push(1) + } + return () => { + if (props.loading) { + return
+
+
+
+
{ + arr.map(() => { + return
+ }) + }
+
+ } + return
{slots.default?.()} +
+ } + } +}) diff --git a/docs/components/skeleton/index.md b/docs/components/skeleton/index.md new file mode 100644 index 0000000000000000000000000000000000000000..f4d8d530f056cd29e3df8e0c447397e39ba7d9b7 --- /dev/null +++ b/docs/components/skeleton/index.md @@ -0,0 +1,73 @@ +# Skeleton 骨架屏 +用于在内容加载过程中展示一组占位图形。 + +### 何时使用 +在需要等待加载内容的位置设置一个骨架屏,某些场景下比 Loading 的视觉效果更好。 + +### 基本用法 +基础的骨架效果, 通过 `row` 属性配置占位段落行数。 + +:::demo + +```vue + +``` +::: + +### 显示头像 +通过 avatar 属性显示头像占位图。 + +:::demo + +```vue + +``` +::: + + +### 展示子组件 +将 loading 属性设置成 false 表示内容加载完成,此时会隐藏占位图,并显示 Skeleton 的子组件。 + +:::demo + +```vue + + +``` +::: + +### API +d-skeleton 参数 +| 参数 | 类型 | 默认 | 说明 | +| :-----: | :-------: | :-----: | :-------------------------------------------- | +| row | `number` | `0` | 段落占位图行数 | +| loading | `boolean` | `true` | 是否显示骨架屏,传 `false` 时会展示子组件内容 | +| animate | `boolean` | `true` | 是否开启动画 | +| avatar | `boolean` | `false` | 是否显示头像占位图 | +