Compare commits
2 Commits
03cee79b53
...
22dc129d8f
| Author | SHA1 | Date |
|---|---|---|
|
|
22dc129d8f | |
|
|
64d9f26c62 |
|
|
@ -1,5 +1,5 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<html lang="en" class="bg-[#FCEEF3]">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
|
|
|
|||
|
|
@ -1,251 +0,0 @@
|
|||
<template>
|
||||
<Teleport to="body">
|
||||
<Transition name="dialog">
|
||||
<div v-if="visible" class="dialog-overlay" @click.self="handleOverlayClick">
|
||||
<div class="dialog-container">
|
||||
<!-- 对话框头部 -->
|
||||
<div class="dialog-header" v-if="title || $slots.title">
|
||||
<slot name="title">{{ title }}</slot>
|
||||
<button v-if="closable" class="dialog-close" @click="handleClose">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 4L4 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<path d="M4 4L12 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 对话框内容 -->
|
||||
<div class="dialog-body">
|
||||
<slot>{{ message }}</slot>
|
||||
</div>
|
||||
|
||||
<!-- 对话框底部按钮区域 -->
|
||||
<div class="dialog-footer" v-if="showFooter">
|
||||
<slot name="footer">
|
||||
<button v-if="showCancelButton" class="dialog-button dialog-button-cancel" @click="handleCancel">
|
||||
{{ cancelButtonText }}
|
||||
</button>
|
||||
<button class="dialog-button dialog-button-confirm" @click="handleConfirm">
|
||||
{{ confirmButtonText }}
|
||||
</button>
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
</Teleport>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineProps, defineEmits } from 'vue'
|
||||
|
||||
// Props 定义
|
||||
const props = defineProps({
|
||||
// 是否显示对话框
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 对话框标题
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 对话框消息内容(简单文本内容)
|
||||
message: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 是否显示关闭按钮
|
||||
closable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 是否显示底部按钮区域
|
||||
showFooter: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 是否显示取消按钮
|
||||
showCancelButton: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 确认按钮文本
|
||||
confirmButtonText: {
|
||||
type: String,
|
||||
default: '确认'
|
||||
},
|
||||
// 取消按钮文本
|
||||
cancelButtonText: {
|
||||
type: String,
|
||||
default: '取消'
|
||||
},
|
||||
// 点击遮罩层是否可以关闭对话框
|
||||
closeOnClickOverlay: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
})
|
||||
|
||||
// Emits 定义
|
||||
const emit = defineEmits<{
|
||||
// 关闭事件
|
||||
close: []
|
||||
// 确认事件
|
||||
confirm: []
|
||||
// 取消事件
|
||||
cancel: []
|
||||
}>()
|
||||
|
||||
// 处理关闭操作
|
||||
const handleClose = () => {
|
||||
emit('close')
|
||||
}
|
||||
|
||||
// 处理确认操作
|
||||
const handleConfirm = () => {
|
||||
emit('confirm')
|
||||
}
|
||||
|
||||
// 处理取消操作
|
||||
const handleCancel = () => {
|
||||
emit('cancel')
|
||||
}
|
||||
|
||||
// 处理点击遮罩层
|
||||
const handleOverlayClick = () => {
|
||||
if (props.closeOnClickOverlay) {
|
||||
emit('close')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 遮罩层样式 */
|
||||
.dialog-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
/* 对话框容器样式 */
|
||||
.dialog-container {
|
||||
background-color: #ffffff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
|
||||
width: 90%;
|
||||
max-width: 500px;
|
||||
max-height: 80vh;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 对话框头部样式 */
|
||||
.dialog-header {
|
||||
padding: 16px 20px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* 关闭按钮样式 */
|
||||
.dialog-close {
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 4px;
|
||||
cursor: pointer;
|
||||
color: #999;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.dialog-close:hover {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* 对话框内容样式 */
|
||||
.dialog-body {
|
||||
padding: 20px;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
color: #666;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* 对话框底部样式 */
|
||||
.dialog-footer {
|
||||
padding: 16px 20px;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
/* 按钮样式 */
|
||||
.dialog-button {
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.dialog-button-cancel {
|
||||
background-color: #f5f5f5;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.dialog-button-cancel:hover {
|
||||
background-color: #e8e8e8;
|
||||
}
|
||||
|
||||
.dialog-button-confirm {
|
||||
background-color: #1890ff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.dialog-button-confirm:hover {
|
||||
background-color: #40a9ff;
|
||||
}
|
||||
|
||||
/* 动画样式 */
|
||||
.dialog-enter-active,
|
||||
.dialog-leave-active {
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.dialog-enter-from,
|
||||
.dialog-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.dialog-enter-active .dialog-container,
|
||||
.dialog-leave-active .dialog-container {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.dialog-enter-from .dialog-container {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
|
||||
.dialog-leave-to .dialog-container {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,162 +0,0 @@
|
|||
import { createApp, h, nextTick } from 'vue'
|
||||
import Dialog from './Dialog.vue'
|
||||
|
||||
// 对话框配置接口
|
||||
export interface DialogOptions {
|
||||
// 对话框标题
|
||||
title?: string
|
||||
// 对话框内容
|
||||
message?: string
|
||||
// 是否显示关闭按钮
|
||||
closable?: boolean
|
||||
// 是否显示底部按钮区域
|
||||
showFooter?: boolean
|
||||
// 是否显示取消按钮
|
||||
showCancelButton?: boolean
|
||||
// 确认按钮文本
|
||||
confirmButtonText?: string
|
||||
// 取消按钮文本
|
||||
cancelButtonText?: string
|
||||
// 点击遮罩层是否可以关闭对话框
|
||||
closeOnClickOverlay?: boolean
|
||||
// 确认回调函数
|
||||
onConfirm?: () => void
|
||||
// 取消回调函数
|
||||
onCancel?: () => void
|
||||
// 关闭回调函数
|
||||
onClose?: () => void
|
||||
}
|
||||
|
||||
// Dialog 实例接口
|
||||
interface DialogInstance {
|
||||
show: () => void
|
||||
hide: () => void
|
||||
close: () => void
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建并显示一个对话框
|
||||
* @param options 对话框配置选项
|
||||
* @returns 对话框实例,可用于手动控制显示和隐藏
|
||||
*/
|
||||
export function showDialog(options: DialogOptions): DialogInstance {
|
||||
// 默认配置
|
||||
const defaultOptions: DialogOptions = {
|
||||
title: '',
|
||||
message: '',
|
||||
closable: true,
|
||||
showFooter: true,
|
||||
showCancelButton: true,
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
closeOnClickOverlay: true,
|
||||
onConfirm: () => {},
|
||||
onCancel: () => {},
|
||||
onClose: () => {}
|
||||
}
|
||||
|
||||
// 合并配置
|
||||
const mergedOptions = { ...defaultOptions, ...options }
|
||||
|
||||
// 创建一个容器元素
|
||||
const container = document.createElement('div')
|
||||
|
||||
// 对话框状态
|
||||
let visible = true
|
||||
|
||||
// 创建应用实例
|
||||
const app = createApp({
|
||||
render() {
|
||||
return h(Dialog, {
|
||||
visible,
|
||||
title: mergedOptions.title,
|
||||
message: mergedOptions.message,
|
||||
closable: mergedOptions.closable,
|
||||
showFooter: mergedOptions.showFooter,
|
||||
showCancelButton: mergedOptions.showCancelButton,
|
||||
confirmButtonText: mergedOptions.confirmButtonText,
|
||||
cancelButtonText: mergedOptions.cancelButtonText,
|
||||
closeOnClickOverlay: mergedOptions.closeOnClickOverlay,
|
||||
onConfirm: () => {
|
||||
mergedOptions.onConfirm?.()
|
||||
hideDialog()
|
||||
},
|
||||
onCancel: () => {
|
||||
mergedOptions.onCancel?.()
|
||||
hideDialog()
|
||||
},
|
||||
onClose: () => {
|
||||
mergedOptions.onClose?.()
|
||||
hideDialog()
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// 隐藏对话框
|
||||
function hideDialog() {
|
||||
visible = false
|
||||
// 等待动画完成后卸载组件
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
app.unmount()
|
||||
if (container.parentNode) {
|
||||
container.parentNode.removeChild(container)
|
||||
}
|
||||
}, 300)
|
||||
})
|
||||
}
|
||||
|
||||
// 显示对话框(默认为显示状态)
|
||||
function showDialog() {
|
||||
visible = true
|
||||
}
|
||||
|
||||
// 挂载组件
|
||||
app.mount(container)
|
||||
document.body.appendChild(container)
|
||||
|
||||
// 返回控制方法
|
||||
return {
|
||||
show: showDialog,
|
||||
hide: hideDialog,
|
||||
close: hideDialog
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示一个确认对话框
|
||||
* @param message 确认消息
|
||||
* @param title 对话框标题
|
||||
* @param onConfirm 确认回调
|
||||
* @returns 对话框实例
|
||||
*/
|
||||
export function showConfirmDialog(message: string, title: string = '确认', onConfirm?: () => void): DialogInstance {
|
||||
return showDialog({
|
||||
title,
|
||||
message,
|
||||
showCancelButton: true,
|
||||
onConfirm
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示一个提示对话框
|
||||
* @param message 提示消息
|
||||
* @param title 对话框标题
|
||||
* @returns 对话框实例
|
||||
*/
|
||||
export function showAlertDialog(message: string, title: string = '提示'): DialogInstance {
|
||||
return showDialog({
|
||||
title,
|
||||
message,
|
||||
showCancelButton: false
|
||||
})
|
||||
}
|
||||
|
||||
// 默认导出
|
||||
export default {
|
||||
show: showDialog,
|
||||
confirm: showConfirmDialog,
|
||||
alert: showAlertDialog
|
||||
}
|
||||
|
|
@ -1,304 +0,0 @@
|
|||
# Loading 组件使用文档
|
||||
|
||||
## 组件介绍
|
||||
|
||||
Loading 组件是一个灵活的加载动画组件,支持多种动画类型、自定义大小、颜色等配置,可用于页面加载、数据请求等场景。
|
||||
|
||||
## 组件类型
|
||||
|
||||
- `spinner`:旋转圆环(默认)
|
||||
- `dots`:点状加载动画
|
||||
- `pulse`:脉冲加载动画
|
||||
- `ring`:环形旋转动画
|
||||
|
||||
## 使用方式
|
||||
|
||||
### 方式一:组件方式使用
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div>
|
||||
<!-- 基本使用 -->
|
||||
<Loading :visible="loadingVisible" />
|
||||
|
||||
<!-- 自定义配置 -->
|
||||
<Loading
|
||||
:visible="loadingVisible"
|
||||
type="dots"
|
||||
size="60"
|
||||
color="#1890ff"
|
||||
text="加载中..."
|
||||
:fullscreen="true"
|
||||
background="rgba(0, 0, 0, 0.7)"
|
||||
:opacity="0.8"
|
||||
:strokeWidth="4"
|
||||
strokeLinecap="round"
|
||||
/>
|
||||
|
||||
<button @click="showLoading">显示加载</button>
|
||||
<button @click="hideLoading">隐藏加载</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import Loading from './Loading.vue'
|
||||
|
||||
const loadingVisible = ref(false)
|
||||
|
||||
function showLoading() {
|
||||
loadingVisible.value = true
|
||||
}
|
||||
|
||||
function hideLoading() {
|
||||
loadingVisible.value = false
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
### 方式二:编程方式使用
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div>
|
||||
<button @click="showFullscreenLoading">显示全屏加载</button>
|
||||
<button @click="showLoadingWithText">显示带文本的加载</button>
|
||||
<button @click="showInlineLoading">显示内联加载</button>
|
||||
<button @click="hideAllLoading">隐藏所有加载</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { showLoading, hideLoading, showLoadingWithText, showInlineLoading } from './loading'
|
||||
import type { LoadingInstance } from './loading'
|
||||
|
||||
// 保存加载实例
|
||||
let loadingInstance: LoadingInstance | null = null
|
||||
|
||||
// 显示全屏加载
|
||||
function showFullscreenLoading() {
|
||||
loadingInstance = showLoading({
|
||||
type: 'spinner',
|
||||
size: 50,
|
||||
color: '#1890ff',
|
||||
fullscreen: true,
|
||||
background: 'rgba(255, 255, 255, 0.9)'
|
||||
})
|
||||
}
|
||||
|
||||
// 显示带文本的加载
|
||||
function showLoadingWithText() {
|
||||
loadingInstance = showLoadingWithText('数据加载中,请稍候...', '#52c41a')
|
||||
}
|
||||
|
||||
// 显示内联加载
|
||||
function showInlineLoading() {
|
||||
loadingInstance = showInlineLoading(32, '#fa8c16', 'dots')
|
||||
}
|
||||
|
||||
// 隐藏所有加载
|
||||
function hideAllLoading() {
|
||||
// 方式1:隐藏特定实例
|
||||
if (loadingInstance) {
|
||||
loadingInstance.hide()
|
||||
loadingInstance = null
|
||||
}
|
||||
|
||||
// 方式2:隐藏当前活动的全屏加载(如果有的话)
|
||||
hideLoading()
|
||||
}
|
||||
|
||||
// 模拟异步请求
|
||||
function mockAsyncRequest() {
|
||||
const loading = showLoadingWithText('处理中...')
|
||||
|
||||
setTimeout(() => {
|
||||
// 请求完成后隐藏加载
|
||||
loading.hide()
|
||||
console.log('请求完成')
|
||||
}, 3000)
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
## API 文档
|
||||
|
||||
### Loading 组件 Props
|
||||
|
||||
| 属性名 | 类型 | 默认值 | 说明 |
|
||||
|-------|------|-------|------|
|
||||
| visible | boolean | false | 是否显示加载组件 |
|
||||
| type | 'spinner' \| 'dots' \| 'pulse' \| 'ring' | 'spinner' | 加载动画类型 |
|
||||
| size | number \| string | 40 | 加载动画大小 |
|
||||
| color | string | '#1890ff' | 加载动画颜色 |
|
||||
| fullscreen | boolean | true | 是否全屏显示 |
|
||||
| text | string | '' | 加载文本 |
|
||||
| background | string | 'rgba(255, 255, 255, 0.9)' | 遮罩层背景色(全屏模式下) |
|
||||
| opacity | number | 1 | 遮罩层透明度(全屏模式下) |
|
||||
| strokeWidth | number | 3 | 线条宽度(仅适用于spinner和ring类型) |
|
||||
| strokeLinecap | 'round' \| 'butt' \| 'square' | 'round' | 线条末端样式(仅适用于spinner类型) |
|
||||
|
||||
### loading.ts 函数API
|
||||
|
||||
#### showLoading(options?: LoadingOptions): LoadingInstance
|
||||
|
||||
创建并显示一个加载组件。
|
||||
|
||||
**参数**:
|
||||
- options: LoadingOptions - 加载组件配置选项(与组件Props相同)
|
||||
|
||||
**返回值**:
|
||||
- LoadingInstance - 加载组件实例,包含 show()、hide()、close() 方法
|
||||
|
||||
#### hideLoading(): void
|
||||
|
||||
隐藏当前活动的全屏加载组件。
|
||||
|
||||
#### showLoadingWithText(text: string, color?: string): LoadingInstance
|
||||
|
||||
显示一个带有文本的全屏加载组件。
|
||||
|
||||
**参数**:
|
||||
- text: string - 加载文本
|
||||
- color: string - 加载动画颜色,默认为 '#1890ff'
|
||||
|
||||
**返回值**:
|
||||
- LoadingInstance - 加载组件实例
|
||||
|
||||
#### showInlineLoading(size?: number, color?: string, type?: LoadingType): LoadingInstance
|
||||
|
||||
显示一个小型内联加载组件。
|
||||
|
||||
**参数**:
|
||||
- size: number - 加载组件大小,默认为 24
|
||||
- color: string - 加载动画颜色,默认为 '#1890ff'
|
||||
- type: LoadingType - 加载动画类型,默认为 'spinner'
|
||||
|
||||
**返回值**:
|
||||
- LoadingInstance - 加载组件实例
|
||||
|
||||
### LoadingInstance 接口
|
||||
|
||||
| 方法名 | 说明 |
|
||||
|-------|------|
|
||||
| show() | 显示加载组件 |
|
||||
| hide() | 隐藏加载组件并卸载 |
|
||||
| close() | 同 hide(),隐藏加载组件并卸载 |
|
||||
|
||||
## 示例代码
|
||||
|
||||
### 场景1:页面加载
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div v-if="!loading">
|
||||
<!-- 页面内容 -->
|
||||
</div>
|
||||
<Loading v-else :visible="loading" text="页面加载中..." />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import Loading from './components/Loading.vue'
|
||||
|
||||
const loading = ref(true)
|
||||
|
||||
onMounted(() => {
|
||||
// 模拟页面数据加载
|
||||
setTimeout(() => {
|
||||
loading.value = false
|
||||
}, 2000)
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
### 场景2:API请求加载
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div>
|
||||
<button @click="fetchData" :disabled="loading">获取数据</button>
|
||||
<div v-if="data">
|
||||
<!-- 数据展示 -->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { showLoading, hideLoading } from './components/loading'
|
||||
|
||||
const loading = ref(false)
|
||||
const data = ref(null)
|
||||
|
||||
async function fetchData() {
|
||||
loading.value = true
|
||||
|
||||
try {
|
||||
// 显示加载
|
||||
const loadingInstance = showLoadingWithText('数据请求中...')
|
||||
|
||||
// 模拟API请求
|
||||
await new Promise(resolve => setTimeout(resolve, 2000))
|
||||
|
||||
// 获取数据
|
||||
data.value = { /* 数据内容 */ }
|
||||
} catch (error) {
|
||||
console.error('请求失败:', error)
|
||||
} finally {
|
||||
loading.value = false
|
||||
// 隐藏加载
|
||||
hideLoading()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
### 场景3:提交表单时的加载
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<form @submit.prevent="submitForm">
|
||||
<!-- 表单内容 -->
|
||||
<button type="submit" :disabled="submitting">
|
||||
{{ submitting ? '提交中...' : '提交' }}
|
||||
<Loading
|
||||
v-if="submitting"
|
||||
:visible="true"
|
||||
:fullscreen="false"
|
||||
type="spinner"
|
||||
:size="16"
|
||||
style="display: inline-block; margin-left: 8px;"
|
||||
/>
|
||||
</button>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import Loading from './components/Loading.vue'
|
||||
|
||||
const submitting = ref(false)
|
||||
|
||||
async function submitForm() {
|
||||
submitting.value = true
|
||||
|
||||
try {
|
||||
// 模拟表单提交
|
||||
await new Promise(resolve => setTimeout(resolve, 1500))
|
||||
console.log('表单提交成功')
|
||||
} catch (error) {
|
||||
console.error('表单提交失败:', error)
|
||||
} finally {
|
||||
submitting.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. 当使用编程方式创建多个全屏加载组件时,最新创建的会替换之前的。
|
||||
2. 请确保在不需要加载动画时调用 hide() 方法来卸载组件,避免内存泄漏。
|
||||
3. 对于长时间运行的操作,建议添加加载文本以提高用户体验。
|
||||
4. 内联加载组件不会自动居中,需要根据具体场景调整其位置。
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="min-h-screen bg-[#FCEEF3] overflow-hidden">
|
||||
<div class="h-full bg-[#FCEEF3] overflow-hidden">
|
||||
<!-- 顶部头图 -->
|
||||
<div class="w-full overflow-hidden relative">
|
||||
<img src="/头图.png" alt="活动宣传" class="w-full h-auto" />
|
||||
|
|
|
|||
Loading…
Reference in New Issue