English | 中文
A Vue 3.0 custom directives plugin package, built-in with v-loading, v-skeleton, v-skeleton-avatar, v-skeleton-list, v-error, and v-empty default page directives, focusing on solving scenarios such as waiting, feedback, and error during network requests.
npm i vue-default-page// main.js
// Import the directives
import vueDefaultPage from 'vue-default-page';
import { createApp } from 'vue';
const app = createApp();
// Register the directives
app.use(vueDefaultPage);<!-- demo.vue -->
<div v-loading="true"></div>// main.js
app.use(vueDefaultPage, {
  background: '#000',
  loading: {
    iconColor: '#fff',
    miniIconColor: '#fff',
    textColor: '#fff',
  },
});| Name | Description | Type | Default | 
|---|---|---|---|
| zIndex | The stack level of the directive | number / string | 100 | 
| background | Background color of the mask | string | #fff | 
| loading | v-loading configurations | boolean / VdpLoading | true | 
| skeleton | v-skeleton configurations | boolean / VdpSkeleton | true | 
| skeletonAvatar | v-skeleton-avatar configurations | boolean / VdpSkeletonAvatar | false | 
| skeletonList | v-skeleton-list configurations | boolean / VdpSkeletonList | false | 
| error | v-error configurations | boolean / VdpError | true | 
| empty | v-empty configurations | boolean / VdpEmpty | true | 
// main.js
// Import the directive
import { vdpLoading } from 'vue-default-page';
import { createApp } from 'vue';
const app = createApp();
// Register the directive
app.use(vdpLoading);// main.js
app.use(vdpLoading, {
  background: '#000',
  iconColor: '#fff',
  miniIconColor: '#fff',
  textColor: '#fff',
});| Name | Description | Configurations Type | 
|---|---|---|
| vdpLoading | v-loading | VdpLoading | 
| vdpSkeleton | v-skeleton | VdpSkeleton | 
| vdpSkeletonAvatar | v-skeleton-avatar | VdpSkeletonAvatar | 
| vdpSkeletonList | v-skeleton-list | VdpSkeletonList | 
| vdpError | v-error | VdpError | 
| vdpEmpty | v-empty | VdpEmpty | 
<!-- demo.vue -->
<script setup lang="js">
  // Import the directives creation function
  import { createVueDefaultPage } from 'vue-default-page';
  // Create the directive
  const vLoading = createVueDefaultPage('loading');
</script>
<template>
  <div v-loading="true"></div>
</template>Method 1: Configure in the directives creation function, the detailed configurations is consistent with On-demand Import Global Configuration.
<!-- demo.vue -->
<script setup lang="js">
  // Create the directive
  const vLoading = createVueDefaultPage('loading', {
    background: '#000',
    iconColor: '#fff',
    miniIconColor: '#fff',
    textColor: '#fff',
  });
</script>
<template>
  <div v-loading="true"></div>
</template>Method 2: Add attribute configurations to the element.
<!-- demo.vue -->
<template>
  <div
    v-loading="true"
    vdp-background="#000"
    vdp-loading-icon-color="#fff"
    vdp-loading-mini-icon-color="#fff"
    vdp-loading-text-color="#fff"
  ></div>
</template>Common attribute configurations, for specific directive attribute configurations, please refer to the detailed sections below.
| Name | Description | Type | Default | 
|---|---|---|---|
| vdp-z-index | The stack level of the directive | string | 100 | 
| vdp-background | Background color of the mask | string | #fff | 
<!-- demo.vue -->
<script setup lang="js">
  import { ref } from 'vue';
  // npm i vue-hooks-plus
  import { useRequest } from 'vue-hooks-plus';
  const data = ref([]);
  // Simulate the first request failure, and then refresh to request successfully.
  let times = 0;
  const api = () =>
    new Promise((resolve, reject) => {
      setTimeout(() => {
        data.value = Array.from({ length: 10 }, (v, k) => k);
        times ? resolve('Successful') : reject('Failed');
        times++;
      }, 2000);
    });
  // https://inhiblabcore.github.io/docs/hooks/useRequest
  const { loading, error, refresh } = useRequest(api);
</script>
<template>
  <div v-loading="loading" v-error="[!!error, refresh]" v-empty="!data.length">
    <div v-for="i in data" :key="i">{{ i }}</div>
  </div>
</template>When all directives are true, it will be shown according to the following priority.
v-loading > v-skeleton = v-skeleton-avatar = v-skeleton-list > v-error > v-empty
Custom icon, same configuration as v-error and v-empty.
<!-- demo.vue -->
<script setup lang="js">
  import { createVueDefaultPage } from 'vue-default-page';
  const icon = `<svg class="circle" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 160">
    <path
      d="M151.5,80A71.5,71.5,0,1,1,80,8.5"
      fill="none"
      stroke="#bbb"
      stroke-miterlimit="10"
      stroke-width="16"
    />
  </svg>`;
  // Create the directive
  const vLoading = createVueDefaultPage('loading', {
    icon,
    miniIcon: icon,
  });
</script>
<template>
  <div v-loading="true"></div>
</template>
<style>
  .circle {
    display: block;
    animation: spin 1.5s ease-in-out infinite;
  }
  @keyframes spin {
    100% {
      transform: rotate(360deg);
    }
  }
</style>| Name | Description | Type | Default | 
|---|---|---|---|
| enable | Enable the directive (Enable when Global Configuration) | boolean | true | 
| text | Text | string | Loading… | 
| textColor | Text color | string | #999 | 
| iconColor | Icon color (Disable when custom icon) | string | #bbb | 
| miniIconColor | Mini icon color (Disable when custom mini icon) | string | #bbb | 
| icon | Custom icon | string | — | 
| miniIcon | Custom mini icon | boolean / string | true | 
| iconMaxSize | Maximum size of icon | number / string | 24 | 
| iconShowText | Whether to show text when using large icon | boolean | true | 
| zIndex | The stack level of the directive | number / string | 100 | 
| background | Background color of the mask | string | #fff | 
| Name | Description | Type | Default | 
|---|---|---|---|
| vdp-loading-text | Text | string | Loading… | 
| vdp-loading-text-color | Text color | string | #999 | 
| vdp-loading-icon-color | Icon color (Disable when custom icon) | string | #bbb | 
| vdp-loading-mini-icon-color | Mini icon color (Disable when custom mini ico) | string | #bbb | 
| vdp-loading-icon | Custom icon | string | — | 
| vdp-loading-mini-icon | Custom mini icon | string | — | 
| vdp-loading-icon-max-size | Maximum size of icon | string | 24 | 
Default show avatar and list skeleton, can also be used independently.
<!-- demo.vue -->
<template>
  <div v-skeleton="true"></div>
  <div v-skeleton.avatar="true"></div>
  <div v-skeleton.list="true"></div>
</template>| Name | Description | Type | Default | 
|---|---|---|---|
| enable | Enable the directive (Enable when Global Configuration) | boolean | true | 
| animation | Animation | boolean / ('avatar' | 'list')[] / Animation | true | 
| avatarMaxSize | Maximum size of avatar | number / string | 54 | 
| zIndex | The stack level of the directive | number / string | 100 | 
| background | Background color of the mask | string | #fff | 
| Name | Description | Type | Default | 
|---|---|---|---|
| vdp-skeleton-avatar-max-size | Maximum size of avatar | string | 54 | 
| Name | Description | Type | Default | 
|---|---|---|---|
| avatar | Enable avatar animation | boolean | true | 
| list | Enable list animation | boolean | true | 
Avatar or list skeleton can also be used individually by registering directives, but unlike other directives, these two are false by default and need to be manually enabled.
// main.js
app.use(vueDefaultPage, {
  skeletonAvatar: true,
  skeletonList: true,
});<!-- demo.vue -->
<template>
  <div v-skeleton-avatar="true"></div>
  <div v-skeleton-list="true"></div>
</template>| Name | Description | Type | Default | 
|---|---|---|---|
| enable | Enable the directive (Enable when Global Configuration) | boolean | false | 
| animation | Animation | boolean | true | 
| avatarMaxSize | Maximum size of avatar | number / string | 54 | 
| zIndex | The stack level of the directive | number / string | 100 | 
| background | Background color of the mask | string | #fff | 
| Name | Description | Type | Default | 
|---|---|---|---|
| enable | Enable the directive (Enable when Global Configuration) | boolean | false | 
| animation | Animation | boolean | true | 
| zIndex | The stack level of the directive | number / string | 100 | 
| background | Background color of the mask | string | #fff | 
Like other directives, it can be controlled to show or hide using a Boolean.
<!-- demo.vue -->
<template>
  <div v-error="true"></div>
</template>You can also pass a refresh function in an Array. For detailed usage, refer to Advanced.
<!-- demo.vue -->
<template>
  <div v-error="[error, () => {}]"></div>
</template>| Name | Description | Type | Default | 
|---|---|---|---|
| enable | Enable the directive (Enable when Global Configuration) | boolean | true | 
| text | Text | string | Network Error | 
| refreshText | Refresh text (Enable when refresh function is passed) | boolean / string | , Click to Refresh | 
| textColor | Text color | string | #999 | 
| icon | Custom icon | string | — | 
| miniIcon | Custom mini icon | boolean / string | true | 
| iconMaxSize | Maximum size of icon | number / string | 180 | 
| iconShowText | Whether to show text when using large icon | boolean | true | 
| zIndex | The stack level of the directive | number / string | 100 | 
| background | Background color of the mask | string | #fff | 
| Name | Description | Type | Default | 
|---|---|---|---|
| vdp-error-text | Text | string | Network Error | 
| vdp-error-refresh-text | Refresh text (Enable when refresh function is passed) | string | , Click to Refresh | 
| vdp-error-text-color | Text color | string | #999 | 
| vdp-error-icon | Custom icon | string | — | 
| vdp-error-mini-icon | Custom mini icon | string | — | 
| vdp-error-icon-max-size | Maximum size of icon | string | 180 | 
All directives will automatically adjust their height according to the container's size, and they have different display states.
<!-- demo.vue -->
<template>
  <div v-empty="true" style="height: 500px;"></div>
  <div v-empty="true"></div>
</template>The maximum icon size can be adjusted using the iconMaxSize or the vdp-empty-icon-max-size (v-skeleton series directives allow only the avatarMaxSize to change the maximum avatar size).
<!-- demo.vue -->
<template>
  <div
    v-empty="true"
    style="height: 500px;"
    vdp-empty-icon-max-size="400"
  ></div>
</template>| Name | Description | Type | Default | 
|---|---|---|---|
| enable | Enable the directive (Enable when Global Configuration) | boolean | true | 
| text | Text | string | No Data | 
| textColor | Text color | string | #999 | 
| icon | Custom icon | string | — | 
| miniIcon | Custom mini icon | boolean / string | false | 
| iconMaxSize | Maximum size of icon | number / string | 180 | 
| iconShowText | Whether to show text when using large | boolean | true | 
| zIndex | The stack level of the directive | number / string | 100 | 
| background | Background color of the mask | string | #fff | 
| Name | Description | Type | Default | 
|---|---|---|---|
| vdp-empty-text | Text | string | No Data | 
| vdp-empty-text-color | Text color | string | #999 | 
| vdp-empty-icon | Custom icon | string | — | 
| vdp-empty-mini-icon | Custom mini icon | string | — | 
| vdp-empty-icon-max-size | Maximum size of icon | string | 180 | 
Vue-Default-Page uses px by default and design width is 375. You can use plugins such as postcss-px-to-viewport to convert to viewport units.
// vite.config.js
import pxToViewport from 'postcss-px-to-viewport';
export default defineConfig(() => {
  return {
    css: {
      postcss: {
        plugins: [pxToViewport({ viewportWidth: 375 })],
      },
    },
  };
});Thank element-plus for providing inspiration.
MIT.