Nuxt.js,像Vue一样,支持插件,可以有三种类型:定制的插件,Vue插件,以及外部包和模块。虽然Nuxt文档详细讨论了后两者,但他们只简单地解释了如何在你的Nuxt应用程序中构建和使用自定义插件。
一个全局的自定义插件在一些情况下可以派上用场。例如,让我们想象一下,你无法为你试图实现的功能找到一个开源插件,或者你对你找到的插件不完全满意。或者,也许你觉得有点创意,而且你手上有一些时间。
在本教程中,我们将介绍使用Vue和JavaScript建立我们自己的自定义插件的两种不同选择。作为一个例子,我们的自定义插件将在你的Nuxt应用程序的控制台中显示我的生日,但你可以根据你的项目需求进行个性化定制。让我们开始吧!
构建组件
第一步是构建Vue组件。对于这篇文章,我们将使用一个基本的toast组件,它将显示简单的成功和错误信息。我已经为这篇文章构建了一个,我们稍后会详细讨论它:
<template>
<div class="toast-element">
<div :class="['toast-container', { success: state === 'success', error: state === 'error' }]">
<div class="icon">
<svg
v-if="state === 'success'"
width="8"
height="7"
viewBox="0 0 8 7"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M6.96304 0.962891L2.88896 5.37647L1.03711 3.3703" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
</svg>
<svg
v-else
width="3"
height="10"
viewBox="0 0 3 10"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M1 1.6665V4.99984" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
<path d="M1 8.3335H1.00833" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</div>
<p>
{{ message }}
</p>
</div>
</div>
</template>
<script>
export default {
data () {
return {
toastIsVisible: false,
message: '',
state: ''
}
},
mounted () {
this.$store.subscribe((mutation, state) => {
if (mutation.type === 'toast/showToast') {
this.message = state.toast.content
this.state = state.toast.state
this.toastIsVisible = true
document.querySelector('.toast-element').classList.add('enter')
setTimeout(() => {
if (this.toastIsVisible) {
this.removeToast()
}
}, 3000)
}
})
},
methods: {
removeToast () {
document.querySelector('.toast-element').classList.replace('enter', 'leave')
setTimeout(() => {
this.toastIsVisible = false
}, 240)
}
}
}
</script>
<style scoped>
.toast-element {
position: fixed;
top: -90px;
left: 0;
width: 100%;
height: max-content;
display: flex;
justify-content: center;
align-items: center;
z-index: 7;
opacity: 0;
transition: all 240ms cubic-bezier(0, 0.0, 0.2, 1) 0s;
}
.enter {
top: 20px;
opacity: 1;
}
.leave {
top: 20px;
transform: scale(0.9);
}
.toast-container {
width: fit-content;
border: 1px solid transparent;
border-radius: 5px;
padding: 0.9375rem 1.875rem;
display: grid;
grid-template-columns: repeat(2, max-content);
column-gap: 0.9375rem;
align-items: center;
}
.success {
border-color: #037F10;
background-color: #F4FFF6;
}
.error {
border-color: #FF2525;
background-color: #FFF4F4;
}
.icon {
border-radius: 50%;
display: flex;
}
.success .icon {
padding: 6px;
background-color: #037F10;
}
.error .icon {
padding: 5px 8px 5px 9px;
background-color: #FF2525;
}
p {
width: max-content;
font-size: 1.0625rem;
font-weight: 400;
}
.success p {
color: #037F10;
}
.error p {
color: #FF2525;
}
</style>
吐司组件创建了两个按钮,看起来像下面这样:

吐司组件错误信息:

吐司组件的成功信息
如果你回顾一下toast组件,你会注意到对商店的subscribe() 方法的调用。因为我们的组件是动态的,我们需要从某个地方获得内容,即商店。
商店
在我们的toast组件中,有两个变量,toast消息和它的状态,要么是success ,要么是error 。在Vuex的帮助下,我们将在Nuxt应用程序中存储状态。因此,我们需要一个商店,最好是与应用程序的一般商店不同的商店:
export const state = () => ({
content: '',
state: ''
})
export const mutations = {
showToast (state, payload) {
state.content = payload.content
state.state = payload.state
}
}
订阅组件到商店
现在我们的商店已经准备好了,我们需要在商店和toast组件之间建立一个通信通道。在这里,subscribe() 方法派上了用场,将组件订阅到商店的突变中。因此,它在商店的每次突变后被调用,接收突变和状态对象作为参数。要了解更多关于subscribe() 方法的信息,请查看Vuex API页面上的订阅部分。
因为subscribe() 方法是在商店的每次突变后被调用的,我们需要确认toast商店被突变了。一旦我们确认了这一点,我们就可以继续更新组件的变量、消息和它的状态:
this.$store.subscribe((mutation, state) => {
if (mutation.type === 'toast/showToast') {
this.message = state.toast.content
this.state = state.toast.state
this.toastIsVisible = true
document.querySelector('.toast-element').classList.add('enter')
setTimeout(() => {
if (this.toastIsVisible) {
this.removeToast()
}
}, 3000)
}
})
我们检查突变的类型是toast/showToast ,因为我们的toast存储在toast.js ,而突变的方法是showToast() 。
初始化该插件
现在我们已经完成了组件的构建和功能的实现,我们需要让它在Nuxt应用程序中可用,这样我们就可以在需要时调用show 方法来显示吐司组件;我们将在plugins 文件夹中这样做。
让插件在整个应用中可用也被称为注入插件,Vue为此提供了inject() 函数。这又给show 方法的对象加上了一个$ 的前缀:
export default ({ app, store }, inject) => {
inject('toaster', {
showToast ({ content = '', state = '' }) {
store.commit('toast/showToast', { content, state })
}
})
}
因此,每当我们在Nuxt应用中调用这个$toaster.showToast() 方法时,我们也需要传入content 和state 参数。
然而,如果你的插件是用于一些JavaScript功能,比如在我们的例子中,显示我的生日,那么你只需要下面的代码:
export default ({ app }, inject) => {
inject('displayBirthday', () => {
console.log(`March 3rd!`)
})
}
$displayBirthday() 将记录我的生日到你的控制台。对于这样的情况,你就不需要一个商店或一个组件。
如果你仔细注意了这两段代码,你会注意到inject() 函数的第二个参数的类型不同。第一个是一个对象,而第二个是一个函数。当你的插件可能需要多个动作时,对象类型很有用,而函数则最适合于单个动作。然而,对象中可以只有一个方法。
定义和注册插件
在我们渲染插件之前,我们的Nuxt应用程序需要确认toast插件的存在。我们可以使用nuxt.config.js 文件中的plugins 属性来添加这方面的代码:
export default {
plugins: [
{ src: '~/plugins/toaster' }
]
}
插件的注入代码在plugins/toaster.js 文件中。
使用该插件
这样一来,我们的插件就可以使用了!要看到我们的插件在运行,首先,toast组件需要出现在页面上。然后,我们可以调用我们商店的$toaster.showToast() 方法,并传递content 和state 参数:
this.$toaster.showToast({
content: 'Successfully logged in!',
state: 'success'
})
总结
在这篇文章中,我们已经学会了如何使用Vue和JavaScript在Nuxt应用程序中建立一个全局的自定义插件。你可以使用这个组件在你的应用程序中实现不同类型的功能,当你找不到适合你项目需求的开源插件时,它就派上用场了。我们还讨论了如何去使用该插件的组件,以及当该插件不需要组件时该怎么办。
虽然我们这个教程的例子展示了相当简单的功能,在控制台中显示一个日期,但可以自由地在这个项目的基础上进行定制,以满足你的需求。关于Nuxt插件的更多信息,我建议查看Nuxt文档。祝你建设愉快!