ruler
一个灵活、可链式调用的 TypeScript/JavaScript 校验规则工厂。
特性
- 链式 API,可构建复杂校验规则
- 支持 string、number、array、boolean、object、symbol、bigint、null、undefined
- 可自定义错误信息
- 易于扩展与集成
- 支持 TypeScript
与 UI 框架集成
Varlet UI
vue
<script setup lang="ts">
import { ref } from 'vue'
import { rulerFactory } from 'rattail/ruler'
const r = rulerFactory((validator) => {
return (value) => {
const e = validator(value)
return e ? e.message : true
}
})
const model = ref({
name: '',
email: '',
})
</script>
<template>
<var-form>
<var-input
v-model="model.name"
placeholder="姓名"
:rules="r().required('必填').min(2, '长度不正确').done()"
/>
<var-input
v-model="model.age"
placeholder="邮箱"
:rules="r().email('必须是邮箱格式').done()"
/>
</var-form>
</template>Vant
vue
<script setup lang="ts">
import { ref } from 'vue'
import { rulerFactory } from 'rattail/ruler'
import type { FieldRule } from 'vant'
const r = rulerFactory<FieldRule>((validator, params) => ({
validator(value) {
const e = validator(value)
return e ? e.message : true
},
trigger: ['onChange', 'onBlur', 'onSubmit'],
...params,
}))
const model = ref({
name: '',
email: '',
})
</script>
<template>
<van-form>
<van-cell-group inset>
<van-field
v-model="model.name"
label="姓名"
placeholder="姓名"
:rules="r().required('必填').done()"
/>
<van-field
v-model="model.email"
label="邮箱"
placeholder="邮箱"
:rules="r().email('必须是邮箱格式').done()"
/>
</van-cell-group>
</van-form>
</template>Naive UI
vue
<script setup lang="ts">
import { ref } from 'vue'
import type { FormItemRule } from 'naive-ui'
import { rulerFactory } from 'rattail/ruler'
const r = rulerFactory<FormItemRule>((validator, params = {}) => ({
trigger: ['blur', 'change', 'input'],
validator: (_, value) => validator(value),
...params,
}))
const model = ref({
name: '',
age: 20,
})
</script>
<template>
<n-form :model>
<n-form-item
path="name"
label="姓名"
:rule="r().required('必填').min(2, '长度不正确').done()"
>
<n-input v-model:value="model.name" />
</n-form-item>
<n-form-item
path="age"
label="年龄"
:rule="r().number().required('必填').negative('必须为负数').done()"
>
<n-input-number v-model:value="model.age" />
</n-form-item>
</n-form>
</template>Element Plus
vue
<script setup lang="ts">
import { ref } from 'vue'
import type { FormItemRule } from 'element-plus'
import { rulerFactory } from 'rattail/ruler'
const r = rulerFactory<FormItemRule>((validator, params) => ({
validator(_, value, callback) {
const e = validator(value)
e ? callback(e) : callback()
},
trigger: ['blur', 'change', 'input'],
...params,
}))
const model = ref({
name: '',
email: '',
})
</script>
<template>
<el-form :model>
<el-form-item
prop="name"
label="姓名"
:rules="r().required('必填').done()"
>
<el-input v-model="model.name" />
</el-form-item>
<el-form-item
prop="email"
label="邮箱"
:rules="r().email('必须是邮箱格式').done()"
>
<el-input v-model="model.email" />
</el-form-item>
</el-form>
</template>扩展 API
以 Naive UI 为例
ts
import { FormItemRule } from 'naive-ui'
import {
RulerContext,
rulerFactory,
RulerFactoryMessage,
} from 'rattail/ruler'
interface RulerExtendedContext {
ip(
message: RulerFactoryMessage,
params?: FormItemRule,
): RulerContext<FormItemRule, FormItemRule, this>
}
const r = rulerFactory<
FormItemRule,
FormItemRule,
RulerExtendedContext
>(
(validator, params = {}) => ({
trigger: ['blur', 'change', 'input'],
validator: (_, value) => validator(value),
...params,
}),
(ctx) => {
function ip(message: RulerFactoryMessage, params?: FormItemRule) {
ctx.addRule((value) => {
// 自行实现 isString 和 isIP
if (!isString(value) || !isIP(value)) {
return new Error(ctx.getMessage(message))
}
}, params)
return ctx
}
return { ip }
},
)
r().ip('IP 格式错误').done()API
类型校验
.string(message?, params?).number(message?, params?).array(message?, params?).boolean(message?, params?).object(message?, params?).symbol(message?, params?).bigint(message?, params?).null(message?, params?).undefined(message?, params?).true(message?, params?).false(message?, params?)
非空校验
.required(message)
字符串校验
.min(value, message, params?).max(value, message, params?).length(value, message, params?).regex(regexp, message, params?).startsWith(value, message, params?).endsWith(value, message, params?).includes(value, message, params?).uppercase(message, params?).lowercase(message, params?).email(message, params?)
数字校验
.number().min(value, message, params?).number().max(value, message, params?).number().gt(value, message, params?).number().gte(value, message, params?)别名 .min.number().lt(value, message, params?).number().lte(value, message, params?)别名 .max.number().positive(value, message, params?).number().negative(value, message, params?)
Bigint 校验
.bigint().min(value, message, params?).bigint().max(value, message, params?).bigint().gt(value, message, params?).bigint().gte(value, message, params?)别名 .min.bigint().lt(value, message, params?).bigint().lte(value, message, params?)别名 .max.bigint().positive(value, message, params?).bigint().negative(value, message, params?)
数组校验
.array().min(value, message, params?).array().max(value, message, params?).array().length(value, message, params?).array().includes(value, message, params?)
谓词校验
.is(fn, message, params?).not(fn, message, params?)
完成规则构建
.done()
自定义规则
.addRule(validator)
值转换
.trim().toLowerCase().toUpperCase().transform(fn)