158 lines
3.2 KiB
Markdown
158 lines
3.2 KiB
Markdown
---
|
||
title: VueUse简介和使用
|
||
date: 2026-06-05
|
||
---
|
||
|
||
# 一、安装
|
||
```bash
|
||
npm install @vueuse/core
|
||
```
|
||
|
||
# 二、使用
|
||
## 2.1 实时获取当前时间
|
||
```ts
|
||
<template>
|
||
<div class="card">
|
||
<p>当前时间: {{ formattedTime }}</p>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { useNow, useDateFormat } from '@vueuse/core'
|
||
|
||
// 获取当前时间响应式对象
|
||
const now = useNow()
|
||
|
||
// 格式化时间
|
||
const formattedTime = useDateFormat(now, 'YYYY-MM-DD HH:mm:ss')
|
||
</script>
|
||
```
|
||
|
||
## 2.2 useWebSocket
|
||
```ts
|
||
<script setup lang="ts">
|
||
iconst { status, send } = useWebSocket('wss://example.com/ws', {
|
||
// 连接成功
|
||
onConnected(ws) {
|
||
console.log('WS connected')
|
||
},
|
||
// 收到消息
|
||
onMessage(ws, event) {
|
||
const msg = JSON.parse(event.data)
|
||
console.log('receive:', msg)
|
||
},
|
||
// 断开
|
||
onDisconnected(ws, event) {
|
||
console.log('WS disconnected, code:', event.code)
|
||
},
|
||
onError(ws, event) {
|
||
console.error('WS error', event)
|
||
},
|
||
autoReconnect: {
|
||
retries: 3,
|
||
delay: 1000
|
||
}
|
||
})
|
||
</script>
|
||
```
|
||
|
||
## 2.3 防抖和节流
|
||
| | 防抖 Debounce | 节流 Throttle |
|
||
| :--- | :--- | :--- |
|
||
| **执行时机** | 连续触发 **停下后** | **每隔一段时间** |
|
||
| **执行次数** | 通常 1 次(最后) | 多次,但受限制 |
|
||
| **典型场景** | 搜索联想、校验 | 滚动、拖拽 |
|
||
|
||
  防抖:
|
||
```vue
|
||
<template>
|
||
<input @input="handleInput" placeholder="输入搜索关键字" />
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref } from 'vue'
|
||
import { useDebounceFn } from '@vueuse/core'
|
||
|
||
const keyword = ref('')
|
||
|
||
// 输入停止 500ms 后执行搜索
|
||
const debouncedSearch = useDebounceFn((val) => {
|
||
console.log('发起搜索请求:', val)
|
||
// api.search(val)
|
||
}, 500)
|
||
|
||
const handleInput = (e) => {
|
||
keyword.value = e.target.value
|
||
debouncedSearch(keyword.value)
|
||
}
|
||
</script>
|
||
```
|
||
|
||
  节流:
|
||
```vue
|
||
<template>
|
||
<div style="padding: 20px">
|
||
<p>点击次数(被节流):{{ count }}</p>
|
||
<button @click="throttledClick">
|
||
狂点我(节流 500ms)
|
||
</button>
|
||
<p style="color:#999;font-size:12px">
|
||
快速连点也不会一直 +1,每 500ms 最多加一次
|
||
</p>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref } from 'vue'
|
||
import { useThrottleFn } from '@vueuse/core'
|
||
|
||
const count = ref(0)
|
||
|
||
// 节流函数:500ms 内最多执行一次
|
||
const throttledClick = useThrottleFn(() => {
|
||
count.value++
|
||
console.log('真正执行 +1')
|
||
}, 500)
|
||
</script>
|
||
```
|
||
|
||
::: warning
|
||
如果是表单提交,应该使用状态锁来限制,即当提交后,将按钮置为loading状态,提交成功后再重置。
|
||
```vue
|
||
<template>
|
||
<el-button
|
||
type="primary"
|
||
:loading="loading"
|
||
@click="handleSubmit"
|
||
>
|
||
{{ loading ? '提交中...' : '提交' }}
|
||
</el-button>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref } from 'vue'
|
||
import { ElMessage } from 'element-plus'
|
||
|
||
const loading = ref(false)
|
||
|
||
const handleSubmit = async () => {
|
||
if (loading.value) return
|
||
loading.value = true
|
||
|
||
try {
|
||
// 模拟接口请求
|
||
await submitForm()
|
||
ElMessage.success('提交成功')
|
||
} catch (err) {
|
||
ElMessage.error('提交失败')
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
const submitForm = () => {
|
||
return new Promise(resolve => setTimeout(resolve, 1500))
|
||
}
|
||
</script>
|
||
```
|
||
::: |