npm package: @hbis-uni/hbis-loading
Description: HBIS UNI loading component
Latest version: 1.0.0

# hbis-loading 加载组件

一个功能强大、性能优异的 Vue 3 加载组件，支持自定义样式、触摸关闭和防内存溢出设计。

## 特性

- ✅ 支持参数控制触摸屏幕是否可以销毁
- ✅ 支持自定义 loading 样式和文字信息
- ✅ 采用 CSS 动画，不会导致内存溢出和阻塞主线程
- ✅ 响应式设计，适配不同屏幕尺寸
- ✅ 支持多种加载动画类型
- ✅ 支持自定义插槽，实现完全个性化的加载效果

## 安装

```bash
pnpm add @hbis-uni/hbis-loading
# 或
npm install @hbis-uni/hbis-loading
```

## 基本使用

### 全局注册

```javascript
// main.js
import { createApp } from 'vue';
import App from './App.vue';
import hbisLoading from '@hbis-uni/hbis-loading';

const app = createApp(App);
app.component('hbis-loading', hbisLoading);
app.mount('#app');
```

### 局部使用

```vue
<template>
  <div class="demo">
    <button @click="showLoading">显示加载</button>
    <button @click="hideLoading">隐藏加载</button>
    
    <!-- 基本用法 -->
    <hbis-loading v-model:visible="loadingVisible" text="加载中..." />
    
    <!-- 允许触摸关闭 -->
    <hbis-loading 
      v-model:visible="touchDismissLoading"
      touch-dismiss
      text="触摸屏幕关闭"
    />
    
    <!-- 自定义样式 -->
    <hbis-loading 
      v-model:visible="customLoading"
      spinner-type="dots"
      text="自定义样式"
      :text-style="{ fontSize: '16px', color: '#409eff' }"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue';
import hbisLoading from '@hbis-uni/hbis-loading';

const loadingVisible = ref(false);
const touchDismissLoading = ref(false);
const customLoading = ref(false);

const showLoading = () => {
  loadingVisible.value = true;
  // 3秒后自动隐藏
  setTimeout(() => {
    loadingVisible.value = false;
  }, 3000);
};

const hideLoading = () => {
  loadingVisible.value = false;
  touchDismissLoading.value = false;
  customLoading.value = false;
};
</script>
```

## API

### Props

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `visible` | `Boolean` | `false` | 控制加载组件是否显示，支持 v-model 双向绑定 |
| `touch-dismiss` | `Boolean` | `false` | 是否允许触摸屏幕关闭加载 |
| `text` | `String` | `''` | 加载文字信息 |
| `spinner-type` | `String` | `'circular'` | 加载动画类型：`circular`（圆形）、`dots`（点状）、`bars`（条状） |
| `text-style` | `Object` | `{}` | 自定义文字样式 |
| `container-style` | `Object` | `{}` | 自定义容器样式 |

### Events

| 事件名 | 参数 | 说明 |
|--------|------|------|
| `update:visible` | `Boolean` | 当加载状态改变时触发，用于 v-model 双向绑定 |
| `close` | 无 | 当加载关闭时触发 |

### Slots

| 插槽名 | 说明 |
|--------|------|
| `spinner` | 自定义加载动画插槽，将完全替换默认的加载动画 |

### 暴露的方法

| 方法名 | 参数 | 说明 |
|--------|------|------|
| `show` | 无 | 显示加载组件 |
| `hide` | 无 | 隐藏加载组件 |

## 高级用法

### 自定义加载动画

```vue
<template>
  <hbis-loading v-model:visible="loadingVisible">
    <template #spinner>
      <div class="custom-spinner">
        <div class="custom-circle"></div>
        <div class="custom-circle"></div>
        <div class="custom-circle"></div>
      </div>
    </template>
  </hbis-loading>
</template>

<style scoped>
.custom-spinner {
  display: flex;
  gap: 8px;
}

.custom-circle {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background-color: #409eff;
  animation: bounce 1.4s ease-in-out infinite both;
}

.custom-circle:nth-child(1) {
  animation-delay: -0.32s;
}

.custom-circle:nth-child(2) {
  animation-delay: -0.16s;
}

@keyframes bounce {
  0%, 80%, 100% {
    transform: scale(0);
  }
  40% {
    transform: scale(1);
  }
}
</style>
```

### 与异步操作结合

```vue
<template>
  <div class="demo">
    <button @click="fetchData" :disabled="loading">获取数据</button>
    <hbis-loading v-model:visible="loading" text="正在获取数据..." />
    <div v-if="data" class="data-container">
      {{ data }}
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import hbisLoading from '@hbis-uni/hbis-loading';

const loading = ref(false);
const data = ref(null);

const fetchData = async () => {
  loading.value = true;
  try {
    // 模拟异步请求
    await new Promise(resolve => setTimeout(resolve, 2000));
    data.value = '获取到的数据内容';
  } catch (error) {
    console.error('获取数据失败:', error);
  } finally {
    loading.value = false;
  }
};
</script>
```

## 性能优化

1. **CSS 动画**：使用 CSS 动画而非 JavaScript 动画，避免阻塞主线程
2. **按需渲染**：当 `visible` 为 false 时，组件不会渲染到 DOM 中
3. **内存管理**：组件卸载时会清理所有事件监听器和样式修改
4. **响应式设计**：根据屏幕尺寸自动调整大小，提高移动端性能

## 浏览器兼容性

- ✅ Chrome
- ✅ Firefox
- ✅ Safari
- ✅ Edge
- ✅ 移动端浏览器

## 注意事项

1. 为了避免内存泄漏，请确保在组件销毁时将 `visible` 设置为 false
2. 对于长时间运行的加载操作，建议提供取消按钮或进度提示
3. 在使用自定义插槽时，请注意保持动画的性能，避免使用复杂的 JavaScript 动画

## 示例

### 示例 1：页面加载

```vue
<template>
  <div class="page">
    <hbis-loading 
      v-model:visible="pageLoading"
      text="页面加载中..."
    />
    <div v-if="!pageLoading" class="page-content">
      <!-- 页面内容 -->
    </div>
  </div>
</template>
```

### 示例 2：表单提交

```vue
<template>
  <form @submit.prevent="submitForm">
    <!-- 表单内容 -->
    <button type="submit" :disabled="submitting">提交</button>
    <hbis-loading 
      v-model:visible="submitting"
      touch-dismiss
      text="提交中..."
    />
  </form>
</template>
```

### 示例 3：文件上传

```vue
<template>
  <div class="upload-container">
    <input type="file" @change="handleFileUpload" />
    <hbis-loading 
      v-model:visible="uploading"
      spinner-type="bars"
      text="上传中..."
    />
  </div>
</template>
```

## 常见问题

### Q: 为什么加载动画不显示？
A: 请检查 `visible` 属性是否设置为 true，以及组件是否正确导入和注册。

### Q: 如何实现全屏加载效果？
A: 组件默认就是全屏加载效果，只需设置 `visible` 为 true 即可。

### Q: 如何修改加载遮罩的背景颜色？
A: 可以通过 `container-style` 属性自定义：
```vue
<hbis-loading 
  v-model:visible="loading"
  :container-style="{ backgroundColor: 'rgba(255, 255, 255, 0.8)' }"
/>
```

### Q: 组件会影响页面的滚动吗？
A: 当加载组件显示时，会自动设置 `document.body.style.overflow = 'hidden'` 防止页面滚动，隐藏时会恢复原状。

## 更新日志

### v1.0.0
- ✨ 初始版本
- ✨ 支持触摸关闭功能
- ✨ 支持多种加载动画类型
- ✨ 支持自定义样式和插槽
- ✨ 响应式设计