教程:加载 js-confetti
介绍
在本教程中,您将学习如何使用 Nuxt Scripts 模块加载 js-confetti 脚本。
您将了解以下内容:
- 什么是
useScriptNpm注册脚本。 - 如何使用它来加载
js-confetti脚本。 - 为加载的脚本添加类型。
- 使用代理函数调用脚本。
关于 useScriptNpm 的背景
要加载脚本,我们将使用 useScriptNpm。
这是一个注册脚本,是建立在 useScript 组合式函数之上的受支持第三方集成,允许您从 NPM 加载脚本。
在使用 NPM 文件时,通常会将它们作为 node_module 依赖项包含在 package.json 文件中。然而,优化这些脚本的加载可能很困难,通常需要从单独的代码块动态导入模块,并且只在需要时加载。它还会降低构建速度,因为模块需要被转译。
useScriptNpm 注册脚本抽象了此过程,允许您用一行代码加载那些被导出为可立即调用函数的脚本。
在许多情况下,将脚本作为 package.json 文件中的依赖项可能仍更合理,但对于不常用或对应用不关键的脚本,这可以是一个很好的替代方案。
最开始我们可以将使用该脚本视为 useHead 组合式函数的替代。您可以在以下代码示例中看到抽象层的比较。
useScriptNpm({
packageName: 'js-confetti',
file: 'dist/js-confetti.browser.js',
version: '0.12.0',
})
useScript('https://cdn.jsdelivr.net/npm/js-confetti@0.12.0/dist/js-confetti.browser.js')
useHead({
script: [
{ src: 'https://cdn.jsdelivr.net/npm/js-confetti@latest/dist/js-confetti.browser.js' }
]
})
加载脚本
在您的某个组件中,您将需要加载该脚本。您可以通过使用 useScriptNpm 注册脚本来实现。
<script setup lang="ts">
useScriptNpm({
packageName: 'js-confetti',
file: 'dist/js-confetti.browser.js',
version: '0.12.0',
})
</script>
如果检查浏览器请求,您应该会看到脚本被加载。
解析第三方脚本 API
脚本加载完成后,您可以在组件中使用它。为此,我们需要告诉底层 API 如何使用该脚本,为此可以利用 use 函数。
该函数只会在客户端调用,用于解析第三方脚本。
<script setup lang="ts">
useScriptNpm({
packageName: 'js-confetti',
file: 'dist/js-confetti.browser.js',
version: '0.12.0',
scriptOptions: {
// 告诉 useScript 如何解析第三方脚本
use() {
return { JSConfetti: window.JSConfetti }
},
},
})
</script>
使用第三方脚本 API
既然我们有了解析第三方脚本 API 的方法,就可以开始使用它了。
js-confetti 库要求每次使用时都要实例化一个 JSConfetti 类的新实例,最兼容的处理方式是显式等待脚本加载完成。
但是,如果您喜欢更便捷的 API,也可以使用代理函数。需要注意的是,当在页面之间切换时,这种方式会失效,因为需要在页面间调用 new window.JSConfetti()。
<script setup lang="ts">
const { onLoaded } = useScriptNpm({
packageName: 'js-confetti',
file: 'dist/js-confetti.browser.js',
version: '0.12.0',
scriptOptions: {
use() {
return { JSConfetti: window.JSConfetti }
},
},
})
onLoaded(({ JSConfetti }) => {
// 使用真实的 API 实例
const confetti = new JSConfetti()
confetti.addConfetti({ emojis: ['🌈', '⚡️', '💥', '✨', '💫', '🌸'] })
})
</script>
<script setup lang="ts">
const { proxy } = useScriptNpm({
packageName: 'js-confetti',
file: 'dist/js-confetti.browser.js',
version: '0.12.0',
scriptOptions: {
use: () => typeof window.JSConfetti !== 'undefined' && new window.JSConfetti()
}
})
onMounted(() => {
// 直接使用
proxy.addConfetti({ emojis: ['🌈', '⚡️', '💥', '✨', '💫', '🌸'] })
})
</script>
恭喜!脚本加载后您应该能看到一些表情符号。
不过,您会注意到类型有问题。addConfetti 函数没有类型定义,因此没有智能感知或类型检查。
添加类型
您可以使用 useScriptNpm 组合式函数的泛型为脚本添加类型,并向全局 window 对象添加类型声明。
<script setup lang="ts">
export interface JSConfettiApi {
JSConfetti: {
new (): {
addConfetti: (options?: { emojis: string[] }) => void
}
}
}
declare global {
interface Window extends JSConfettiApi {}
}
const { onLoaded } = useScriptNpm<JSConfettiApi>({
packageName: 'js-confetti',
file: 'dist/js-confetti.browser.js',
version: '0.12.0',
scriptOptions: {
use() {
return { JSConfetti: window.JSConfetti }
},
},
})
onMounted(() => {
onLoaded(({ JSConfetti }) => {
const confetti = new JSConfetti()
// 完全有类型支持!
confetti.addConfetti({ emojis: ['🌈', '⚡️', '💥', '✨', '💫', '🌸'] })
})
})
</script>
额外内容:基于触发条件的脚本加载
您可以使用 trigger 选项延迟加载脚本。如果想在某个事件或某个时间点后加载脚本,这非常有用。
请参考脚本触发器指南了解所有可用选项。
使用 Ref
最简单的方法是使用一个 ref —— 当该 ref 变为真值时,脚本会加载。
<script setup lang="ts">
const shouldLoad = ref(false)
const { onLoaded } = useScriptNpm({
// ..
scriptOptions: {
trigger: shouldLoad
}
})
onLoaded(({ JSConfetti }) => {
const confetti = new JSConfetti()
confetti.addConfetti({ emojis: ['🎉', '🎊', '✨'] })
})
</script>
<template>
<button @click="shouldLoad = true">
点击加载彩带
</button>
</template>
trigger: computed(() => someCondition.value) 或 trigger: () => shouldLoad.value。使用元素事件
您还可以使用 useScriptTriggerElement 组合函数,基于元素交互触发加载。
<script setup lang="ts">
const mouseOverEl = ref<HTMLElement>()
const { onLoaded } = useScriptNpm({
// ..
scriptOptions: {
trigger: useScriptTriggerElement({ trigger: 'mouseover', el: mouseOverEl })
}
})
// ..
onMounted(() => {
onLoaded(({ JSConfetti }) => {
const confetti = new JSConfetti()
confetti.addConfetti({ emojis: ['L', 'O', 'A', 'D', 'E', 'D'] })
})
})
</script>
<template>
<div ref="mouseOverEl">
<h1>鼠标悬停在这里加载彩带</h1>
</div>
</template>
额外内容:打包脚本
由于脚本来自 NPM 并且有版本控制,我们可以将它安全地与应用一起打包。这样可以减少 DNS 请求数量,提升应用性能。
要打包脚本,可以使用 bundle 选项。
<script setup lang="ts">
const script = useScriptNpm({
// ...
scriptOptions: {
bundle: true
}
})
// ..
</script>
您应该能看到脚本是从您的应用服务器加载的。
结论
在本教程中,您学习了如何使用 useScriptNpm 注册脚本加载 js-confetti 脚本。
想了解更多您所接触到的具体概念,请查看关键概念文档。