Vue
来自 tinyval-mask/vue 的 v-mask 指令可以把掩码绑定到字段上。该包运行时不依赖 Vue:指令只是一个普通对象,Vue 仅用于类型。
vue
<script setup lang="ts">
import { ref } from 'vue';
import { phone, money } from 'tinyval-mask/presets';
import { vMask } from 'tinyval-mask/vue';
// create masks once, not inline in the template
const phoneMask = phone();
const moneyMask = money({ currency: '₽' });
const tel = ref('');
const amount = ref('');
</script>
<template>
<input v-model="tel" v-mask="phoneMask" />
<input v-model="amount" v-mask="moneyMask" inputmode="decimal" />
<input v-mask="'99.99.9999'" />
</template>v-model得到的是带掩码的值:+7 (999) 123-45-67。如需去掉掩码的值,请添加.raw修饰符 —— 见下文。- 请在
<script>中创建掩码:像v-mask="phone()"这样的表达式会在每次渲染时创建新的掩码。 - 指令可以放在包裹元素上 —— 它会找到内部的
<input>。这样掩码就能用于 UI 组件库的字段。 - 全局注册:
app.directive('mask', vMask)。
去掉掩码的值 —— .raw
使用 .raw 修饰符时,输入框显示掩码,而 v-model 得到的是去掉掩码的值 —— 与 unmask 的返回值相同。可以直接保存:
vue
<input v-model="tel" v-mask.raw="phoneMask" /> <!-- tel: '79991234567' -->
<input v-model="amount" v-mask.raw="moneyMask" /> <!-- amount: '1500.5' -->模型中的值会带掩码显示:tel = '79991234567' → 输入框显示 +7 (999) 123-45-67。即使 Vue 重新渲染输入框,在中间编辑时光标也不会跳动。
可见模板
传入占位字符 —— 获得焦点时输入框会显示完整模板,光标位于第一个空位:
vue
<input v-model="tel" v-mask.raw="{ mask: phoneMask, placeholder: '_' }" placeholder="Phone" />
<!-- on focus: +7 (___) ___-__-__ typing: +7 (999) 12_-__-__ -->- 模板不会进入
v-model:不使用.raw时为+7 (999) 12,使用.raw时为7999912。 - 空输入框失去焦点时会被清空 —— 显示普通的
placeholder提示。部分填写的输入框会保留模板。 - 数字掩码没有模板:它们的长度不固定。
与 tinyval-vue 一起使用
v-mask 可以用于 <TvField> 以及任何 tinyval-vue 表单字段。使用 .raw 时表单直接得到数字,Schema 无需 unmask 即可校验:
vue
<script setup lang="ts">
import { object, string, pipe, length } from 'tinyval';
import { useForm, TvForm, TvField, TvError } from 'tinyval-vue';
import { phone } from 'tinyval-mask/presets';
import { vMask } from 'tinyval-mask/vue';
const phoneMask = phone();
const Contact = object({
phone: pipe(string(), length(11)),
});
const form = useForm(Contact, { initial: { phone: '' } });
</script>
<template>
<TvForm :form="form" @submit="(data) => api.post('/contacts', data)">
<TvField name="phone" v-mask.raw="{ mask: phoneMask, placeholder: '_' }" inputmode="tel" />
<TvError name="phone" />
</TvForm>
</template>字段中显示 +7 (999) 123-45-67;form.values.phone 和 data 中为 79991234567。
UI 组件库
vue
<el-input v-model="tel" v-mask="phoneMask" />
<v-text-field v-model="tel" v-mask="phoneMask" />