在本指南中,我们将一步步讲解如何创建、注册和使用自定义输入。具体来说,我们将创建一个"一次性密码"输入(简称"OTP")。OTP通常用于两步验证,当用户需要输入通过短信或验证器应用发送的代码时。让我们开始吧!
本指南假设您正在使用标准的 Vue 3 构建工具,如 Vite、Nuxt 3 或 Vue CLI,这将允许您导入 .vue
单文件组件。
首先,让我们创建输入的组件文件。我们将其命名为 OneTimePassword.vue
:
<script setup>
const props = defineProps({
context: Object,
})
</script>
<template>
<div>这里还有更多内容...</div>
</template>
FormKit 提供了许多我们想要保留的开箱即用的输入特性 —— 如标签、帮助文本和显示错误消息。我们真正想要修改的只是我们输入的输入部分。我们可以通过使用 @formkit/vue
包中的 createInput
实用函数来保留这些标准的 FormKit 特性。
当我们构建输入时,我们会想要可视化其进度,所以让我们创建一个示例表单来:
OneTimePassword.vue
createInput()
<FormKit>
组件的 type
属性。我们将这个示例表单命名为 Register.vue
:
太好了!现在我们可以迭代我们的 OneTimePassword.vue
文件并查看结果。首先要注意的是,我们的输入已经支持标签、帮助文本、验证和其他通用的 FormKit 属性。这些特性都是 createInput()
提供的。
另外,注意上面例子中的 <pre>
标签吗?它正在输出表单数据的当前状态。我们将使用这个来可视化我们自定义输入的值。由于我们的输入目前没有值,所以它在表单的数据中不会出现。是时候改变这个情况了!
让我们再次打开 OneTimePassword.vue
,并将我们的 <div>
改为 <input>
标签。我们将从一个单独的文本输入开始,然后从那里开始工作。但是我们如何实际设置和显示我们自定义输入的值呢?
所有自定义输入都会将强大的 context 对象 作为 context
属性传递。为了让我们的输入能够 设置 其值,它需要调用 context.node.input(value)
。为了正确地 显示 我们输入的值,我们应该将输入的 :value
属性设置为 context._value
。
我们的小输入已经长大了!它可能看起来不太好看,但现在它可以读取和写入值了。作为证明,尝试将表单的 values
对象的初始值设置为 { two_factor_code: '12345' }
,你会看到输入自动填充了值。
好的,现在我们已经理解了如何创建输入,如何使用它,以及如何读取和写入值 - 让我们来解决我们一次性密码输入的实际"业务逻辑"。以下是我们的要求:
<input>
标签。对于我们的第一个要求,我们需要 n
个 <input>
标签。也许最好将数字的数量作为一个 prop 暴露出来。为了做到这一点,我们需要告诉我们的 createInput
函数,我们想要接受一个新的 prop:
createInput(OneTimePassword, {
props: ['digits'],
})
我们现在可以访问 context.digits
。回到 OneTimePassword.vue
,让我们使用它来输出正确数量的 <input>
标签。
好的 - 我们有了多个输入!我们的第一个要求已经完成:
<input>
标签。我们在上面的例子中添加了一点 CSS,但总的来说,我们不打算在这个指南中深入研究样式。建议使用 context.classes.yourKey
作为你的输入元素的类名。
注意在上面的例子中,当你在一个输入框中输入时,所有其他的输入框都同步到相同的值了吗?挺酷的,但不是我们想要的。这是因为我们仍然在使用相同的输入处理器和 :value
。以下是我们改进输入的计划:
focus()
。digits
相同时,我们通过调用 context.node.input()
更新输入的值。太好了!这开始像我们期望的那样工作。让我们再次检查我们的要求:
<input>
标签。看起来我们只剩下一件事要做了 —— 支持复制和粘贴。幸运的是,浏览器有一个 paste
事件。为了确保我们的用户体验是一流的,我们会做一个假设:如果用户正在复制/粘贴,他们试图复制和粘贴整个代码。而不是代码的单个数字。这似乎是合理的。
我们需要做的就是捕获我们的任何输入标签上的复制/粘贴事件,获取正在粘贴的文本,并将 tmp
值设置为那个数字字符串。让我们再写一个事件处理器:
handlePaste(e) {
const paste = e.clipboardData.getData('text')
if (typeof paste === 'string') {
// 如果长度正确,就粘贴它。
this.tmp = paste.substr(0, this.max)
const inputs = e.target.parentElement.querySelectorAll('input')
// 聚焦在最后一个字符上
inputs.item(this.tmp.length - 1).focus()
}
}
我们的所有要求都已经完成了!
现在我们已经制作了一个出色的输入,让我们将它注册到我们的应用程序中,这样我们就可以在任何地方只需使用字符串 otp
就可以使用它。打开你的 Vue 应用程序的主文件(app.use(formKit)
所在的地方)。我们只需添加一下:
import { createApp } from 'Vue'
import App from 'App.vue'
import OneTimePassword from './OneTimePassword.vue'
import { plugin, defaultConfig, createInput } from '@formkit/vue'
const app = createApp(App)
app.use(
plugin,
defaultConfig({
inputs: {
otp: createInput(OneTimePassword, {
props: ['digits'],
}),
},
})
)
app.mount('#app')
完成!现在你可以在你的应用程序的任何地方使用你的输入:
<FormKit type="otp" digits="4" />
我们的一次性密码输入工作得很好!以下是我们可以进一步完善的一些额外功能的想法:
希望这个指南帮助你理解如何声明、编写和注册自定义输入。如果你想深入了解,试着阅读关于FormKit 的核心内部和创建自定义输入的内容!