vueuse实践及分析

# 简介

VueUse 是一个基于 Composition API 的实用函数集合。通俗的来说,这就是一个工具函数包,它可以帮助你快速实现一些常见的功能,免得你自己去写,解决重复的工作内容。以及进行了基于 Composition API 的封装。让你在 vue3 中更加得心应手。

VueUse 通过vue-demi (opens new window)的强大功能在单个包中适用于 Vue 2 和 3!;ueUse是基于Compomit API (opens new window)的实用程序函数的集合。

如果想看到每一个实用程序的完整列表,我绝对建议你去看看官方文档 (opens new window)。但总结一下,VueUse中有9种类型的函数。

  1. Animation——包含易于使用的过渡、超时和计时功能。
  2. Browser——可用于不同的屏幕控制、剪贴板、偏好等。
  3. Component——提供了不同组件方法的简写。
  4. Formatters——提供响应时间格式化功能。
  5. Sensors——用来监听不同的DOM事件、输入事件和网络事件。
  6. State——管理用户状态(全局、本地存储、会话存储)。
  7. Utility——不同的实用函数,如 getter、条件、引用同步等。
  8. Watch——更多高级类型的观察器,如可暂停的观察器、退避的观察器和条件观察器。
  9. Misc——不同类型的事件、WebSockets和web workers 的功能

这些类别中的大多数都包含几个不同的功能,所以VueUse对于你的使用情况来说是很灵活的,可以作为一个很好的地方来快速开始构建Vue应用程序。

总体上分为以下几个类别提供工具函数:

  • 动画
  • 浏览器
  • 组件
  • 格式化
  • 传感器
  • State(状态机)
  • 公共方法
  • 监听
  • 杂项

# 安装

# npm

npm i @vueuse/core

npm i @vueuse/core @vueuse/components
1
2
3

# cdn

<script src="https://unpkg.com/@vueuse/shared"></script>
<script src="https://unpkg.com/@vueuse/core"></script>
1
2

建议使用NPM,因为它使用法更容易理解,但如果我们使用CDN,VueUse将在应用程序中通过 window.VueUse 访问。

对于NPM的安装,所有的功能都可以通过使用标准的对象重构从 @vueuse/core 中导入,像这样访问。

import { useRefHistory } from '@vueuse/core'
1

好了,现在我们已经安装了VueUse,让我们在应用程序中使用它!

# 用法示例

# 基础示范

只需从中导入所需的功能@vueuse/core

import { useMouse, usePreferredDark, useLocalStorage } from '@vueuse/core'

export default {
  setup() {
    // 跟踪鼠标位置
    const { x, y } = useMouse()

    // 用户喜欢黑色主题吗
    const isDark = usePreferredDark()

    // 在localStorage中持久化状态
    const store = useLocalStorage(
      'my-storage', 
      {
        name: 'Apple',
        color: 'red',
      },
    )

    return { x, y, isDark, store }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

上面从 VueUse 当中导入了三个函数, useMouseusePreferredDarkuseLocalStorage

  • useMouse 是一个监听当前鼠标坐标的一个方法,他会实时的获取鼠标的当前的位置。
  • usePreferredDark 是一个判断用户是否喜欢深色的方法,他会实时的判断用户是否喜欢深色的主题。
  • useLocalStorage 是一个用来持久化数据的方法,他会把数据持久化到本地存储中。

# 防抖节流

import { useThrottle , useDebounce } from '@vueuse/core'

const input = ref('')
const throttled = useThrottle(input, 1000, false)  // 延迟1s获取 input 的值

const debounced = useDebounce(input, 1000)
input.value = 'bar'
console.log(debounced.value)  // 延迟1s 更新input的值
1
2
3
4
5
6
7
8

# component 中使用的函数

<script setup>
import { ref } from 'vue'
import { onClickOutside } from '@vueuse/core'

const el = ref()
function close () {
  /* ... */
}
onClickOutside(el, close)
</script>

<template>
  <div ref="el">
    Click Outside of Me
  </div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

上面例子中,使用了 onClickOutside 函数,这个函数会在点击元素外部时触发一个回调函数。也就是这里的 close 函数。在 component 中就是这么使用

<script setup>
import { OnClickOutside } from '@vueuse/components'

function close () {
  /* ... */
}
</script>

<template>
  <OnClickOutside @trigger="close">
    <div>
      Click Outside of Me
    </div>
  </OnClickOutside>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

注意⚠️ 这里的 OnClickOutside 函数是一个组件,不是一个函数。需要package.json 中安装了 @vueuse/components

# 全局状态共享的函数

// store.js
import { createGlobalState, useStorage } from '@vueuse/core'
export const useGlobalState = createGlobalState(
  () => useStorage('vue-use-local-storage'),
)

// component.js
import { useGlobalState } from './store'
export default defineComponent({
  setup() {
    const state = useGlobalState()
    return { state }
  },
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14

这样子就是一个简单的状态共享了。扩展一下。传一个参数,就能改变 store 的值了。

# fetch简单的请求

import { useFetch } from '@vueuse/core'
const { isFetching, error, data } = useFetch(url)
1
2

它还有很多的 option 参数,可以自定义。

// 100ms超时
const { data } = useFetch(url, { timeout: 100 })

// 请求拦截
const { data } = useFetch(url, {
  async beforeFetch({ url, options, cancel }) {
    const myToken = await getMyToken()
    if (!myToken) cancel()
    options.headers = {
      ...options.headers,
      Authorization: `Bearer ${myToken}`,
    }
    return {
      options
    }
  }
})

// 响应拦截
const { data } = useFetch(url, {
  afterFetch(ctx) {
    if (ctx.data.title === 'HxH')
      ctx.data.title = 'Hunter x Hunter' // Modifies the resposne data
    return ctx
  },
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 配置

这些显示了 VueUse 中大多数函数的常规配置。

# 事件过滤器

从 v4.0 开始,我们提供了事件过滤器系统,以便灵活地控制何时触发事件。例如,您可以使用 并控制事件触发速率:throttleFilter``debounceFilter

import { throttleFilter, debounceFilter, useLocalStorage, useMouse } from '@vueuse/core'

// 更改将写入localStorage,并设置1s
const storage = useLocalStorage('my-key', { foo: 'bar' }, { eventFilter: throttleFilter(1000) })

// 鼠标位置将在鼠标空闲100ms后更新
const { x, y } = useMouse({ eventFilter: debounceFilter(100) })
1
2
3
4
5
6
7

此外,您可以利用暂时暂停某些事件。pausableFilter

import { pausableFilter, useDeviceMotion } from '@vueuse/core'

const motionControl = pausableFilter()
const motion = useDeviceMotion({ eventFilter: motionControl.eventFilter })

motionControl.pause() // 运动更新停顿了一下
motionControl.resume()// 运动更新恢复
1
2
3
4
5
6
7

# 无功时序

VueUse 的功能遵循 Vue 的反应性系统默认值,尽可能进行冲洗计时 (opens new window)

对于类似 -like 的可组合对象(例如,每当 (opens new window)使用时 (opens new window)暂停监视 (opens new window)存储使用 RefHistory, (opens new window)默认值为 。这意味着它们将缓冲无效的效果并异步刷新它们。这可以避免在同一"tick"中发生多个状态突变时不必要的重复调用。watch``{ flush: 'pre' }

与 使用 的方式相同,VueUse 允许您通过传递以下选项来配置计时:watch``flush

const { pause, resume } = pausableWatch(
  () => {
    // 安全访问更新后的DOM
  },
  { flush: 'post' }
)
1
2
3
4
5
6

刷新选项(默认:"pre")

  • 'pre':在同一个"勾号"中缓冲无效效果,并在渲染之前刷新它们
  • 'post':像"pre"一样的异步,但在组件更新后触发,以便您可以访问更新的DOM
  • 'sync':强制效果始终同步触发

**注意:**对于类似可组合物(例如syncRef (opens new window)controlledComputed (opens new window),当刷新计时可配置时,默认值更改为将它们与 Vue 中计算的引用的工作方式保持一致。computed``{ flush: 'sync' }

# 可配置的全局依赖关系

在 v4.0 中,访问浏览器 API 的函数将提供一个选项字段,供您指定全局依赖项(例如 、和 )。默认情况下,它将使用全局实例,因此在大多数情况下,您无需担心它。在使用 iframe 和测试环境时,此配置非常有用。window``document``navigator

// 访问父上下文中
const parentMousePos = useMouse({ window: window.parent })
const iframe = document.querySelect('#my-iframe')

// 接触子上下文
const childMousePos = useMouse({ window: iframe.contextWindow })
// 测试
const mockWindow = /* ... */
const { x, y } = useMouse({ window: mockWindow })
1
2
3
4
5
6
7
8
9

# 组件

在 v5.0 中,我们引入了一个新包,提供可组合函数的无渲染组件样式用法。@vueuse/components

# 安装

$ npm i @vueuse/core @vueuse/components
1

# 使用

有关组件样式的详细用法,请参阅每个函数的文档。

例如onClickOutside (opens new window) 以前

<script setup>
import { ref } from 'vue'
import { onClickOutside } from '@vueuse/core'

const el = ref()
function close () {
  /* ... */
}

onClickOutside(el, close)
</script>

<template>
  <div ref="el">
    Click Outside of Me
  </div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

现在,您可以以组件方式使用它:

<script setup>
import { OnClickOutside } from '@vueuse/components'

function close () {
  /* ... */
}
</script>

<template>
  <OnClickOutside @trigger="close">
    <div>
      Click Outside of Me
    </div>
  </OnClickOutside>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

同样,您也可以使用 以下命令访问返回值:v-slot

<UseMouse v-slot="{ x, y }">
  x: {{ x }}
  y: {{ y }}
</UseMouse>
<UseDark v-slot="{ isDark, toggleDark }">
  <button @click="toggleDark()">
    Is Dark: {{ isDark }}
  </button>
</UseDark>
1
2
3
4
5
6
7
8
9

useTemplateRefsList

useTemplateRefsList: 这个方法可以在 vue3 组件式 api 中帮助你快速绑定 for 循环中的 组件ref。比自己实现考虑得更加完备。

<script setup lang="ts">
import { onUpdated } from 'vue'
import { useTemplateRefsList } from '@vueuse/core'

const refs = useTemplateRefsList<HTMLDivElement>() // 用来存储元素 ref 的数组

onUpdated(() => {
  console.log(refs)
})
</script>
<template>
  <!-- 在这里绑定 ref -->
  <div v-for="i of 5" :key="i" :ref="refs.set"></div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 5个常用的函数

# useRefHistory

# useRefHistory 跟踪响应式数据的更改

useRefHistory 跟踪对Ref所做的每一个改变,并将其存储在一个数组中。这使我们能够轻松地为我们的应用程序提供撤销和重做功能。

让我们看一个示例,其中我们正在构建一个我们希望能够撤消的文本区域。

第一步是在不使用 VueUse 的情况下创建我们的基本组件——使用 ref、textarea 和用于撤消和重做的按钮。

<template>
  <p> 
    <button> Undo </button>
    <button> Redo </button>
  </p>
  <textarea v-model="text"/>
</template>

<script setup>
import { ref } from 'vue'
const text = ref('')
</script>

<style scoped>
  button {
    border: none;
    outline: none;
    margin-right: 10px;
    background-color: #2ecc71;
    color: white;
    padding: 5px 10px;
  }
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

然后,让我们通过导入 useRefHistory 函数,然后从我们的文本 ref 中提取history、undo 和 redo 属性来添加 VueUse。这就像调用 useRefHistory 并传递我们的 ref 一样简单。

import { ref } from 'vue'
import { useRefHistory } from '@vueuse/core'

const text = ref('')
const { history, undo, redo } = useRefHistory(text)
1
2
3
4
5

每次我们的 ref 更改时,这都会触发一个观察者——更新我们刚刚创建的 history 属性。

然后,为了让我们能真正看到发生了什么,让我们打印出模板内的历史记录,同时在点击相应的按钮时调用我们的 undoredo 函数。

<template>
  <p> 
    <button @click="undo"> Undo </button>
    <button @click="redo"> Redo </button>
  </p>
  <textarea v-model="text"/>
  <ul>
    <li v-for="entry in history" :key="entry.timestamp">
      {{ entry }}
    </li>
  </ul>
</template>

<script setup>
import { ref } from 'vue'
import { useRefHistory } from '@vueuse/core'
const text = ref('')
const { history, undo, redo } = useRefHistory(text)
</script>

<style scoped>
  button {
    border: none;
    outline: none;
    margin-right: 10px;
    background-color: #2ecc71;
    color: white;
    padding: 5px 10px;;
  }
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

好的,让我们运行它。当我们输入时,每个字符都会触发历史数组中的一个新条目,如果我们点击undo/redo,我们会转到相应的条目。

image-20220213132845023

还有不同的选项可以为此功能添加更多功能。例如,我们可以深入跟踪反应对象并限制这样的历史条目的数量。

const { history, undo, redo } = useRefHistory(text, {
  deep: true,
  capacity: 10,
})
1
2
3
4

有关完整的选项清单,请务必查看文档。

# onClickOutside

# onClickOutside 关闭模态

onClickOutside 检测在一个元素之外的任何点击。根据我的经验,这个功能最常见的使用情况是关闭任何模式或弹出窗口。

通常情况下,我们希望我们的模态挡住网页的其他部分,以吸引用户的注意力并限制错误。然而,如果他们真的点击了模态之外的内容,我们希望它能够关闭。

只需两个步骤即可完成此操作:

  1. 为我们要检测的元素创建一个模板引用
  2. 使用此模板引用运行 onClickOutside

这是一个使用 onClickOutside 的带有弹出窗口的简单组件。

<template>
  <button @click="open = true"> Open Popup </button>
  <div class="popup" v-if='open'>
    <div class="popup-content" ref="popup">
      Lorem ipsum dolor sit amet consectetur adipisicing elit. Corporis aliquid autem reiciendis eius accusamus sequi, ipsam corrupti vel laboriosam necessitatibus sit natus vero sint ullam! Omnis commodi eos accusantium illum?
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { onClickOutside } from '@vueuse/core'
const open = ref(false) // state of our popup
const popup = ref() // template ref
// whenever our popup exists, and we click anything BUT it
onClickOutside(popup, () => {
  open.value  = false
})
</script>

<style scoped>
  button {
    border: none;
    outline: none;
    margin-right: 10px;
    background-color: #2ecc71;
    color: white;
    padding: 5px 10px;;
  }
  .popup {
    position: fixed;
    top: ;
    left: ;
    width: 100vw;
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(, , , 0.1);
  }
  .popup-content {
    min-width: 300px;
    padding: 20px;
    width: 30%;
    background: #fff;
  }
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

结果是这样的,我们可以用我们的按钮打开弹出窗口,然后在弹出内容窗口外点击关闭它。

image-20220213133455868

# useVModel

# useVModel 简化了 v-model 绑定

Vue 开发人员的一个常见用例是为组件创建自定义 v-model 绑定。这意味着我们的组件接受一个值作为 prop,并且每当该值被修改时,我们的组件都会向父级发出更新事件。

image-20220213134554782

useVModel函数将其简化为只使用标准的 ref 语法。假设我们有一个自定义的文本输入,试图为其文本输入的值创建一个 v-model。 通常情况下,我们必须接受一个值的prop,然后emit一个变化事件来更新父组件中的数据值。

我们可以使用useVModel,把它当作一个普通的ref,而不是使用ref并调用 props.valueupdate:value。这有助于减少我们需要记住的不同语法的数量!

<template>
  <div>
    <input 
           type="text" 
           :value="data"
           @input="update"
           />
  </div>
</template>

<script>
import { useVModel } from '@vueuse/core'
export default {
  props: ['data'],
  setup(props, { emit }) {
    const data = useVModel(props, 'data', emit)
    console.log(data.value) // equal to props.data
    data.value = 'name' // equal to emit('update:data', 'name')
    const update = (event) => {
        data.value = event.target.value
    }
    return {
        data,
        update
    }
  },
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

每当我们需要访问我们的值时,我们只需调用 .value,useVModel将从我们的组件props中给我们提供值。而每当我们改变对象的值时,useVModel会向父组件发出一个更新事件

下面是一个快速的例子,说明该父级组件可能是什么样子...

<template>
  <div>
    <p> {{ data }} </p>
    <custom-input 
      :data="data" 
      @update:data="data = $event"
    />
  </div>
</template>

<script>
import CustomInput from './components/CustomInput.vue'
import { ref } from 'vue'
export default {
  components: {
    CustomInput,
  },
  setup () {
    const data = ref('hello')
    return {
      data
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

结果看起来像这样,我们在父级中的值始终与子级中的输入保持同步。

image-20220213135115523

# IntersectionObserver

# 使用IntersectionObserver 跟踪元素可见性

在确定两个元素是否重叠时,Intersection Observers (opens new window) 非常强大。一个很好的用例是检查元素当前是否在视口中可见。

本质上,它检查目标元素与根元素/文档相交的百分比。如果该百分比超过某个阈值,它会调用一个回调来确定目标元素是否可见。

useIntersectionObserver 提供了一个简单的语法来使用IntersectionObserver API。我们所需要做的就是为我们想要检查的元素提供一个模板ref。默认情况下,IntersectionObserver将以文档的视口为根基,阈值为0.1——所以当这个阈值在任何一个方向被越过时,我们的交集观察器将被触发。

这个例子的代码可能是这样的:我们有一个假的段落,只是在我们的视口中占据了空间,我们的目标元素,然后是一个打印语句,打印我们元素的可见性。

<template>
  <p> Is target visible? {{ targetIsVisible }} </p>
  <div class="container">
    <div class="target" ref="target">
      <h1>Hello world</h1>
    </div>
  </div>
</template>

<script>
import { ref } from 'vue'
import { useIntersectionObserver } from '@vueuse/core'
export default {
  setup() {
    const target = ref(null)
    const targetIsVisible = ref(false)
    const { stop } = useIntersectionObserver(
      target,
      ([{ isIntersecting }], observerElement) => {
        targetIsVisible.value = isIntersecting
      },
    )
    return {
      target,
      targetIsVisible,
    }
  },
}
</script>

<style scoped>
.container {
  width: 80%;
  margin:  auto;
  background-color: #fafafa;
  max-height: 300px;
  overflow: scroll;
}
.target {
  margin-top: 500px;
  background-color: #1abc9c;
  color: white;
  padding: 20px;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

当我们运行并滚动它时,我们会看到它正确地更新了。

image-20220213135327191我们还可以为 Intersection Observer 指定更多选项,例如更改其根元素、边距(用于计算交点的根边界框的偏移量)和阈值级别。

const { stop } = useIntersectionObserver(
  target,
  ([{ isIntersecting }], observerElement) => {
    targetIsVisible.value = isIntersecting
  },
  {
    // root, rootMargin, threshold, window
    // full options in the source: https://github.com/vueuse/vueuse/blob/main/packages/core/useIntersectionObserver/index.ts
    threshold: 0.5,
  }
)
1
2
3
4
5
6
7
8
9
10
11

同样重要的是,这个方法返回一个 stop 函数,我们可以调用这个函数来停止观察交叉点。如果我们只想追踪一个元素在屏幕上第一次可见的时候,这就特别有用。

在这段代码中,一旦 targetIsVisible 被设置为 true,观察者就会停止,即使我们滚动离开目标元素,我们的值也会保持为true

const { stop } = useIntersectionObserver(
  target,
  ([{ isIntersecting }], observerElement) => {
    targetIsVisible.value = isIntersecting
    if (isIntersecting) {
      stop()
    }
  },
)
1
2
3
4
5
6
7
8
9

# useTransition

# useTransition 在值之间过渡

useTransition 是整个veuse库中我最喜欢的函数之一。它允许我们在一行内平滑地转换数值。

我们有一个存储为ref的数字源和一个将在不同数值之间缓和的输出。例如,假设我们想建立一个计数器

image-20220213140038589

我们可以通过三个步骤来做到这一点:

  • 创建我们的 count ref并将其初始化为零;
  • 使用 useTransition 创建 output ref(设置持续时间和转换类型);
  • 更改 count 的值;
<script setup>
import { ref } from 'vue'
import { useTransition, TransitionPresets } from '@vueuse/core'

const source = ref(0)
const output = useTransition(source, {
  duration: 3000,
  transition: TransitionPresets.easeOutExpo,
})
source.value = 5000
</script>
1
2
3
4
5
6
7
8
9
10
11

然后,在我们的模板中,我们希望显示 output 的值,因为它可以在不同值之间平滑过渡。

<template>
  <h2> 
    <p> Join over </p>
    <p> {{ Math.round(output) }}+ </p>
    <p>Developers </p>
  </h2>
</template>

<script setup>
import { ref } from 'vue'
import { useTransition, TransitionPresets } from '@vueuse/core'
const source = ref()
const output = useTransition(source, {
  duration: 3000,
  transition: TransitionPresets.easeOutExpo,
})
source.value = 5000
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

这就是结果!

image-20220213140324329

我们还可以使用 useTransition 来过渡整个数字数组,这在处理位置或颜色时很有用。 处理颜色的一个绝招是使用一个计算属性将RGB值格式化为正确的颜色语法。

<template>
  <h2 :style="{ color: color } "> COLOR CHANGING </h2>
</template>

<script setup>
import { ref, computed } from 'vue'
import { useTransition, TransitionPresets } from '@vueuse/core'
const source = ref([, , ])
const output = useTransition(source, {
  duration: 3000,
  transition: TransitionPresets.easeOutExpo,
})
const color = computed(() => {
  const [r, g, b] = output.value
  return `rgb(${r}, ${g}, ${b})`
})
source.value = [255, , 255]
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

image-20220213140402202

一些进一步定制的酷方法是使用任何内置的过渡预设或使用CSS缓动函数来定义我们自己的过渡。

# 最佳实践

# 解构

VueUse 中的大多数函数都返回一个refs 对象,您可以使用ES6 的对象析构语法来获取所需的内容。例如:

import { useMouse } from '@vueuse/core'

// “x”和“y”是引用
const { x, y } = useMouse()

console.log(x.value)
const mouse = useMouse()
console.log(mouse.x.value)
1
2
3
4
5
6
7
8

如果您希望将它们用作对象属性样式,则可以使用 打开 ref 的包装。例如:reactive()

import { reactive } from 'vue' 
import { useMouse } from '@vueuse/core'

const mouse = reactive(useMouse())

// "x"和"y"将自动展开, 不需要 `.value` 
console.log(mouse.x)
1
2
3
4
5
6
7

# 常规

  • 从以下位置导入所有 Vue API"vue-demi"
  • 尽可能使用ref代替reactive
  • 尽可能使用选项对象作为参数,以便为将来的扩展提供更灵活的操作。
  • 当包装大量数据时,使用shallowRef代替ref
  • 在使用全局变量时使用configurableWindow(等等),比如window可以灵活地处理多个窗口、测试模拟和SSR。
  • 当涉及尚未由浏览器广泛实现的 Web API 时,还会输出标志isSupported
  • 在内部使用watchwatchEffect时,也要尽可能配置immediateflush选项
  • 使用tryOnUnmounted (opens new window)来优雅地清除副作用
  • 避免使用控制台日志

可以参考 (opens new window)

# 参考链接

https://vueuse.org/

上次更新: 2022/04/15, 05:41:28
×