如何在JavaScript/React中用Jexl验证visibleIf输入的语法合法性?
在React项目中用Jexl实现输入验证
安装Jexl
先在项目中安装Jexl依赖:
npm install jexl # 或 yarn add jexl
实现核心验证函数
你需要一个同时完成语法合法性检查、上下文匹配验证,并确保表达式返回符合预期结果的函数(比如visibleIf需要布尔值),以下是实现逻辑:
import Jexl from 'jexl'; // 验证Jexl表达式的函数 const validateJexl = (expression, context) => { const jexlInstance = new Jexl(); try { // 第一步:编译表达式,检查语法是否合法 const compiledExpr = jexlInstance.compile(expression); // 第二步:用给定上下文求值,确保能正常运行 const result = compiledExpr.evalSync(context); // 第三步:验证返回值类型(visibleIf需要布尔值) if (typeof result !== 'boolean') { return '表达式必须返回布尔值'; } // 验证通过,返回null表示无错误 return null; } catch (err) { // 捕获语法错误、上下文缺失等异常 return err.message; } };
React组件示例(弹窗+输入验证)
结合你的场景,实现带验证的visibleIf输入弹窗组件,实时反馈错误(红色边框+错误提示):
import { useState, useCallback } from 'react'; import Jexl from 'jexl'; const VisibleIfEditor = ({ currentQuestionKey, onSave }) => { const [visibleIfExpr, setVisibleIfExpr] = useState(''); const [validationError, setValidationError] = useState(null); // 构造动态上下文(根据当前questionKey生成) const getContext = useCallback(() => { return { answer: { [currentQuestionKey]: "yes" // 用当前questionKey作为键,模拟用户输入值 } }; }, [currentQuestionKey]); // 触发验证的函数 const validateExpression = useCallback(() => { if (!visibleIfExpr.trim()) { setValidationError('表达式不能为空'); return; } const error = validateJexl(visibleIfExpr, getContext()); setValidationError(error); }, [visibleIfExpr, getContext]); // 防抖优化实时验证性能 const debouncedValidate = useCallback( debounce(validateExpression, 500), [validateExpression] ); // 保存逻辑(仅在验证通过时执行) const handleSave = () => { if (!validationError && visibleIfExpr.trim()) { onSave(visibleIfExpr); } }; // 防抖工具函数 function debounce(func, delay) { let timeoutId; return (...args) => { clearTimeout(timeoutId); timeoutId = setTimeout(() => func.apply(this, args), delay); }; } return ( <div className="visible-if-editor"> <h3>设置显示条件</h3> <textarea value={visibleIfExpr} onChange={(e) => { setVisibleIfExpr(e.target.value); debouncedValidate(); }} onBlur={validateExpression} className={`input-field ${validationError ? 'error' : ''}`} placeholder='例如:answer.yes == "yes"' /> {validationError && <p className="error-text">{validationError}</p>} <button onClick={handleSave} disabled={!!validationError || !visibleIfExpr.trim()}> 保存 </button> </div> ); }; export default VisibleIfEditor;
样式示例(实现红色边框)
在CSS中添加错误状态的样式:
.input-field.error { border: 2px solid #dc3545; outline: none; } .error-text { color: #dc3545; margin: 8px 0 0 0; font-size: 14px; }
关键说明
- 语法检查:通过
jexl.compile()捕获语法错误(比如运算符错误、未闭合括号等) - 上下文验证:通过
evalSync()确保表达式能在给定上下文中正常求值,避免引用不存在的属性 - 返回值校验:强制
visibleIf表达式返回布尔值,确保逻辑符合预期 - 性能优化:用防抖减少实时验证的频率,避免频繁编译和求值
内容的提问来源于stack exchange,提问作者Jakub
相关产品推荐
相关产品推荐

