Node.js中使用Joi如何自定义错误消息及客户端可用方案?
嘿,刚好我之前在多语言项目里折腾过Joi的自定义错误提示和客户端使用,给你分享下可行的方案:
一、给Joi设置自定义非英文错误消息
Joi本身就支持替换默认的英文提示,两种方式都很实用:
1. 给单个字段规则单独设置
这种方式适合针对特定字段定制个性化提示,直接在字段的验证链后面加.messages()方法就行,还能用上Joi的占位符动态替换参数:
const Joi = require('joi'); const userSchema = Joi.object({ username: Joi.string() .min(3) .max(20) .required() .messages({ 'string.empty': '用户名不能为空', 'string.min': '用户名长度不能少于{#limit}个字符', 'string.max': '用户名长度不能超过{#limit}个字符', 'any.required': '用户名是必填项' }), email: Joi.string() .email() .required() .messages({ 'string.email': '请输入有效的邮箱地址', 'any.required': '邮箱是必填项' }) }); // 验证示例 const { error } = userSchema.validate({ username: 'ab', email: 'invalid' }); if (error) { console.log(error.details[0].message); // 输出对应的中文提示 }
上面的{#limit}会自动替换成你设置的规则参数(比如min里的3),不用硬写死数值,很灵活。
2. 全局统一配置错误消息
要是你项目里大部分字段的错误提示逻辑都一致,不想每个schema都重复写.messages(),可以用Joi.defaults()全局覆盖默认模板,还能配合.label()给字段设置友好名称:
const Joi = require('joi'); // 全局生成一个带中文提示的Joi实例 const customJoi = Joi.defaults((schema) => { return schema.messages({ 'string.empty': '{{#label}}不能为空', 'string.min': '{{#label}}长度不能少于{{#limit}}个字符', 'string.max': '{{#label}}长度不能超过{{#limit}}个字符', 'string.email': '{{#label}}格式不正确', 'any.required': '{{#label}}是必填项' }); }); // 用这个定制后的实例定义schema const userSchema = customJoi.object({ username: customJoi.string().min(3).max(20).required().label('用户名'), email: customJoi.string().email().required().label('邮箱') });
这种方式特别适合多语言切换场景,把不同语言的消息存在配置文件里,切换时只需要替换全局的消息对象就行。
二、在客户端使用Joi
当然可以!Joi现在已经支持浏览器环境了,你可以直接用npm安装后,通过Webpack、Vite这类打包工具把它整合到前端项目里。如果追求更小的打包体积,也可以用专门为浏览器优化的joi-browser(不过现在主包的浏览器支持已经做得很好了)。
举个Vue项目里的简单示例:
- 先安装Joi:
npm install joi
- 在组件里使用:
<template> <div class="form-group"> <input v-model="username" placeholder="请输入用户名"> <p class="error" v-if="errorMsg">{{ errorMsg }}</p> <button @click="checkForm">提交</button> </div> </template> <script> import Joi from 'joi'; export default { data() { return { username: '', errorMsg: '' }; }, methods: { checkForm() { // 定义验证规则和中文提示 const schema = Joi.string().min(3).max(20).required().messages({ 'string.empty': '用户名不能为空', 'string.min': '用户名长度不能少于3个字符', 'any.required': '用户名是必填项' }); const { error } = schema.validate(this.username); if (error) { this.errorMsg = error.details[0].message; } else { this.errorMsg = ''; // 验证通过,执行提交逻辑 } } } }; </script>
⚠️ 注意:客户端验证只是用来提升用户体验的,服务器端的验证绝对不能省略!前端的验证很容易被绕过,必须在服务器端再做一次校验,才能保证数据的安全性和合法性。
要是你觉得Joi在前端有点重,也可以考虑yup、zod这类更轻量的前端验证库,但如果你已经熟悉Joi的用法,直接用它完全没问题。
内容的提问来源于stack exchange,提问作者Raz
相关产品推荐
相关产品推荐

