浏览代码

upd: skeleton骨架屏组件 (#882)

* upd: 骨架屏组件
liqiong-lab 4 年之前
父节点
当前提交
8ccb6a6034

+ 9 - 0
src/config.json

@@ -879,6 +879,15 @@
         },
         },
         {
         {
           "version": "3.0.0",
           "version": "3.0.0",
+          "name": "Skeleton",
+          "type": "component",
+          "cName": "骨架屏",
+          "desc": "骨架屏",
+          "sort": 23,
+          "show": true,
+          "taro": true,
+          "author": "liqiong"
+        },{
           "name": "Cascader",
           "name": "Cascader",
           "type": "component",
           "type": "component",
           "cName": "级联选择",
           "cName": "级联选择",

+ 105 - 0
src/packages/__VUE/skeleton/common.ts

@@ -0,0 +1,105 @@
+import { h, onMounted, CSSProperties } from 'vue';
+import { computed, PropType, toRefs } from 'vue';
+export type avatarShape = 'round' | 'square';
+
+export const component = {
+  props: {
+    //每行宽度
+    width: {
+      type: String,
+      default: '100px'
+    },
+    //每行高度
+    height: {
+      type: String,
+      default: '100px'
+    },
+    //是否显示动画
+    animated: {
+      type: Boolean,
+      default: false
+    },
+    //头像
+    avatar: {
+      type: Boolean,
+      default: false
+    },
+    //头像形状:正方形/圆形
+    avatarShape: {
+      type: String as PropType<avatarShape>,
+      default: 'round'
+    },
+    //头像大小
+    avatarSize: {
+      type: String,
+      default: '50px'
+    },
+    //是否显示骨架屏
+    loading: {
+      type: Boolean,
+      default: true
+    },
+    //标题/段落 圆角风格
+    round: {
+      type: Boolean,
+      default: false
+    },
+
+    //显示段落行数
+    row: {
+      type: String,
+      default: '1'
+    },
+
+    //是否显示段落标题
+    title: {
+      type: Boolean,
+      default: true
+    }
+  },
+
+  setup(props: any) {
+    const { avatarShape, round, avatarSize } = toRefs(props);
+
+    const avatarClass = computed(() => {
+      const prefixCls = 'avatarClass';
+      return {
+        [prefixCls]: true,
+        [`${prefixCls}--${avatarShape.value}`]: avatarShape.value
+      };
+    });
+
+    const blockClass = computed(() => {
+      const prefixCls = 'blockClass';
+      return {
+        [prefixCls]: true,
+        [`${prefixCls}--round`]: round.value
+      };
+    });
+
+    const getStyle = (): CSSProperties => {
+      const style: CSSProperties = {};
+      if (avatarSize?.value) {
+        return {
+          width: avatarSize.value,
+          height: avatarSize.value
+        };
+      }
+      return {
+        width: '50px',
+        height: '50px'
+      };
+    };
+
+    onMounted(() => {
+      console.log('row', props.row);
+    });
+
+    return {
+      avatarShape,
+      avatarClass,
+      blockClass,
+      getStyle
+    };
+  }
+};

+ 80 - 0
src/packages/__VUE/skeleton/demo.vue

@@ -0,0 +1,80 @@
+<template>
+  <view class="demo">
+    <h2>基础用法</h2>
+
+    <nut-skeleton width="250px" height="15px" animated> </nut-skeleton>
+
+    <h2>传入多行</h2>
+
+    <nut-skeleton width="250px" height="15px" title animated row="3"> </nut-skeleton>
+
+    <h2>显示头像</h2>
+    <nut-skeleton width="250px" height="15px" title animated avatar row="3"> </nut-skeleton>
+
+    <h2>标题段落圆角风格</h2>
+    <nut-skeleton width="250px" height="15px" animated round></nut-skeleton>
+
+    <h2>显示子组件</h2>
+
+    <view class="content">
+      <nut-switch v-model="checked" size="15px" />
+
+      <nut-skeleton width="250px" height="15px" title animated avatar row="3" :loading="!checked">
+        <view class="container">
+          <nut-avatar
+            size="50"
+            icon="https://img14.360buyimg.com/imagetools/jfs/t1/167902/2/8762/791358/603742d7E9b4275e3/e09d8f9a8bf4c0ef.png"
+          />
+          <view class="right-content">
+            <view class="title">NutUI</view>
+            <view class="desc"
+              >一套京东风格的轻量级移动端Vue组库,提供丰富的基础组件和业务组件,帮助开发者快速搭建移动应用。</view
+            >
+          </view>
+        </view>
+      </nut-skeleton>
+    </view>
+  </view>
+</template>
+
+<script lang="ts">
+import { ref } from 'vue';
+import { createComponent } from '../../utils/create';
+const { createDemo } = createComponent('skeleton');
+
+export default createDemo({
+  setup() {
+    const checked = ref(false);
+
+    return {
+      checked
+    };
+  }
+});
+</script>
+
+<style lang="scss">
+.content {
+  .nut-switch {
+    margin: 0 16px 8px 0;
+  }
+  .container {
+    display: flex;
+    .right-content {
+      margin-left: 19px;
+      font-family: PingFangSC;
+      display: flex;
+      flex-direction: column;
+      .title {
+        font-size: 14px;
+        color: rgba(51, 51, 51, 1);
+      }
+      .desc {
+        margin-top: 10px;
+        font-size: 13px;
+        color: rgba(154, 155, 157, 1);
+      }
+    }
+  }
+}
+</style>

+ 99 - 0
src/packages/__VUE/skeleton/doc.md

@@ -0,0 +1,99 @@
+# Skeleton 骨架屏
+
+### 介绍
+
+在页面上待加载区域填充灰色的占位图,本质上是界面加载过程中的过渡效果。
+
+### 安装
+
+```javascript
+
+import { createApp } from 'vue';
+// vue
+import { Skeleton } from '@nutui/nutui';
+// taro
+import { Skeleton } from '@nutui/nutui-taro';
+
+const app = createApp();
+app.use(Skeleton);
+
+```
+
+### 代码实例
+
+### 基础用法
+
+```html
+<nut-skeleton width="250px" height="15px" animated> </nut-skeleton>
+```
+
+### 传入多行
+
+```html
+ <nut-skeleton width="250px" height="15px" title animated row="3"> </nut-skeleton>
+```
+
+
+### 显示头像
+
+```html
+<nut-skeleton width="250px" height="15px" title animated avatar row="3"> </nut-skeleton>
+```
+
+
+### 标题段落圆角风格
+
+```html
+<nut-skeleton width="250px" height="15px" animated round></nut-skeleton>
+```
+
+
+### 显示子组件
+
+```html
+    <div class="content">
+      <nut-switch v-model="checked" size="15px" />
+
+      <nut-skeleton width="250px" height="15px" title animated avatar row="3" :loading="!checked">
+        <div class="container">
+          <nut-avatar
+            size="50"
+            icon="https://img14.360buyimg.com/imagetools/jfs/t1/167902/2/8762/791358/603742d7E9b4275e3/e09d8f9a8bf4c0ef.png"
+          />
+          <div class="right-content">
+            <div class="title">NutUI</div>
+            <div class="desc"
+              >一套京东风格的轻量级移动端Vue组库,提供丰富的基础组件和业务组件,帮助开发者快速搭建移动应用。</div
+            >
+          </div>
+        </div>
+      </nut-skeleton>
+    </div>
+```
+
+
+
+
+
+### Prop  
+
+| 字段       | 说明                                             | 类型    | 默认值    |
+|------------|-------------------------------------------------|---------|----------|
+| loading    | 是否显示骨架屏                                    | Boolean | `true`    | 
+| width       | 每行宽度                                        | String  | `default` |
+| height      | 每行高度                                        | String  | `100px`   |
+| animated    | 是否开启骨架屏动画                                | Boolean  | `false`  |
+| avatar      | 是否显示头像                                     | Boolean | `false`   |
+| avatar-shape      | 头像形状:正方形/圆形                        | String | `round`   |
+| avatar-size       | 头像大小                                   | String | `50px`    |
+| round  | 标题/段落是否采用圆角风格                                | Boolean | `false`  |
+| row    | 设置段落行数                                           | String | `1`       |
+| title  | 是否显示段落标题                                        | Boolean | `true`   |
+
+
+### Slots
+
+| 名称    | 说明           |
+|---------|---------------|
+| default | 骨架屏显示内容  |
+

+ 57 - 0
src/packages/__VUE/skeleton/index.scss

@@ -0,0 +1,57 @@
+.skeleton {
+  display: inline-block;
+  position: relative;
+  overflow: hidden;
+  vertical-align: middle;
+  .content {
+    display: flex;
+    .avatarClass {
+      margin-right: 20px;
+      background: rgb(239, 239, 239);
+    }
+
+    .blockClass,
+    .blockClass--round {
+      width: 100%;
+      height: 100%;
+      background: rgb(239, 239, 239);
+      margin-top: 10px;
+      &:last-child {
+        width: 70% !important;
+      }
+    }
+    .blockClass--round {
+      border-radius: 10px;
+    }
+
+    .content-line {
+      display: flex;
+      flex-direction: column;
+      .title {
+        width: 30%;
+        height: 15px;
+        background: #efefef;
+      }
+    }
+  }
+
+  .skeleton-animation {
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    z-index: 1;
+    background: linear-gradient(90deg, hsla(0, 0%, 100%, 0), hsla(0, 0%, 100%, 0.5) 50%, hsla(0, 0%, 100%, 0) 80%);
+    background-repeat: no-repeat;
+    animation: backpos 2s ease-in-out 0s infinite;
+  }
+  @keyframes backpos {
+    0% {
+      background-position-x: -500px;
+    }
+    to {
+      background-position-x: calc(500px + 100%);
+    }
+  }
+}

+ 31 - 0
src/packages/__VUE/skeleton/index.taro.vue

@@ -0,0 +1,31 @@
+<template>
+  <view v-if="!loading">
+    <slot></slot>
+  </view>
+  <view v-else class="skeleton">
+    <view class="skeleton-animation"></view>
+    <view class="content">
+      <nut-avatar
+        v-if="avatar"
+        :class="avatarClass"
+        :shape="avatarShape"
+        :style="getStyle()"
+        bg-color="rgb(239, 239, 239)"
+      ></nut-avatar>
+
+      <view v-if="Number(row) == 1" :class="blockClass" :style="{ width, height }"> </view>
+
+      <view class="content-line">
+        <view v-if="title" class="title"></view>
+        <view v-for="(item, index) in Number(row)" :key="index" :class="blockClass" :style="{ width, height }"> </view
+      ></view>
+    </view>
+  </view>
+</template>
+
+<script lang="ts">
+import { createComponent } from '../../utils/create';
+import { component } from './common';
+const { create } = createComponent('skeleton');
+export default create(component);
+</script>

+ 31 - 0
src/packages/__VUE/skeleton/index.vue

@@ -0,0 +1,31 @@
+<template>
+  <view v-if="!loading">
+    <slot></slot>
+  </view>
+  <view v-else class="skeleton">
+    <view class="skeleton-animation"></view>
+    <view class="content">
+      <nut-avatar
+        v-if="avatar"
+        :class="avatarClass"
+        :shape="avatarShape"
+        :style="getStyle()"
+        bg-color="rgb(239, 239, 239)"
+      ></nut-avatar>
+
+      <view v-if="Number(row) == 1" :class="blockClass" :style="{ width, height }"> </view>
+
+      <view class="content-line">
+        <view v-if="title" class="title"></view>
+        <view v-for="(item, index) in Number(row)" :key="index" :class="blockClass" :style="{ width, height }"> </view
+      ></view>
+    </view>
+  </view>
+</template>
+
+<script lang="ts">
+import { createComponent } from '../../utils/create';
+import { component } from './common';
+const { create } = createComponent('skeleton');
+export default create(component);
+</script>

+ 1 - 0
src/sites/mobile-taro/vue/src/app.config.ts

@@ -75,6 +75,7 @@ export default {
         'pages/badge/index',
         'pages/badge/index',
         'pages/tag/index',
         'pages/tag/index',
         'pages/popover/index',
         'pages/popover/index',
+        'pages/skeleton/index',
         'pages/cascader/index'
         'pages/cascader/index'
       ]
       ]
     },
     },

+ 3 - 0
src/sites/mobile-taro/vue/src/dentry/pages/skeleton/index.config.ts

@@ -0,0 +1,3 @@
+export default {
+  navigationBarTitleText: 'Skeleton'
+};

+ 74 - 0
src/sites/mobile-taro/vue/src/dentry/pages/skeleton/index.vue

@@ -0,0 +1,74 @@
+<template>
+  <view class="demo">
+    <h2>基础用法</h2>
+    <nut-skeleton width="250px" height="15px" animated> </nut-skeleton>
+
+    <h2>传入多行</h2>
+    <nut-skeleton width="250px" height="15px" title animated row="3"> </nut-skeleton>
+
+    <h2>显示头像</h2>
+    <nut-skeleton width="250px" height="15px" title animated avatar row="3"> </nut-skeleton>
+
+    <h2>标题段落圆角风格</h2>
+    <nut-skeleton width="250px" height="15px" animated round></nut-skeleton>
+
+    <h2>显示子组件</h2>
+    <view class="content">
+      <nut-switch v-model="checked" size="15px" />
+      <nut-skeleton width="250px" height="15px" title animated avatar row="3" :loading="!checked">
+        <view class="container">
+          <nut-avatar
+            size="50"
+            icon="https://img14.360buyimg.com/imagetools/jfs/t1/167902/2/8762/791358/603742d7E9b4275e3/e09d8f9a8bf4c0ef.png"
+          />
+          <view class="right-content">
+            <view class="title">NutUI</view>
+            <view class="desc"
+              >一套京东风格的轻量级移动端Vue组库,提供丰富的基础组件和业务组件,帮助开发者快速搭建移动应用。</view
+            >
+          </view>
+        </view>
+      </nut-skeleton>
+    </view>
+  </view>
+</template>
+
+<script lang="ts">
+import { ref } from 'vue';
+
+export default {
+  setup() {
+    const checked = ref(false);
+
+    return {
+      checked
+    };
+  }
+};
+</script>
+
+<style lang="scss">
+.content {
+  .nut-switch {
+    margin: 0 16px 8px 0;
+  }
+  .container {
+    display: flex;
+    .right-content {
+      margin-left: 19px;
+      font-family: PingFangSC;
+      display: flex;
+      flex-direction: column;
+      .title {
+        font-size: 14px;
+        color: rgba(51, 51, 51, 1);
+      }
+      .desc {
+        margin-top: 10px;
+        font-size: 13px;
+        color: rgba(154, 155, 157, 1);
+      }
+    }
+  }
+}
+</style>