在react-querybuilder中添加自定义运算符后,使用formatQuery生成json-logic时自定义规则失效的问题
嘿,我完全懂你现在的困惑——这个坑确实挺隐蔽的,官方文档这块儿确实没说太清楚。让我帮你拆解一下问题出在哪,以及怎么解决:
问题的核心原因
你已经做了两个关键步骤:在QueryBuilder里注册自定义运算符、给json-logic添加对应的运算逻辑,但漏掉了最关键的一步:告诉formatQuery函数如何把你的自定义运算符转换成json-logic能识别的结构。
formatQuery(尤其是针对jsonlogic格式时)并不会自动读取你给json-logic注册的add_operation配置,它本身有一套默认的运算符映射规则。遇到不认识的自定义运算符时,它要么直接忽略该规则,要么返回false,这就是你看到的现象。
解决方法(两种可选,推荐第一种)
方法一:在自定义运算符定义中直接添加json-logic转换规则
这是最简洁的方式,直接在你定义customOperators的时候,给每个自定义运算符加上jsonLogic属性,告诉formatQuery怎么把它转成json-logic节点:
// 注意:用json-logic的var语法引用字段,同时把字符串值转成数字匹配运算逻辑 const customOperators = [ { name: 'lengthequals', label: 'Length =', jsonLogic: (field, value) => ({ lengthequals: [{ var: field }, Number(value)] }) }, { name: 'lengthgreaterthan', label: 'Length >', jsonLogic: (field, value) => ({ lengthgreaterthan: [{ var: field }, Number(value)] }) }, { name: 'lengthlessthan', label: 'Length <', jsonLogic: (field, value) => ({ lengthlessthan: [{ var: field }, Number(value)] }) }, ];
这里有个细节要注意:把value转成Number类型,因为你在json-logic的运算逻辑里是做数字比较的,而QueryBuilder里用户输入的value默认是字符串(比如"4"),不转的话会导致类型不匹配。
方法二:在formatQuery调用时传入全局转换规则
如果你不想修改运算符的定义,可以在调用formatQuery的时候,通过第三个参数(配置选项)里的operatorTransform函数来统一处理自定义运算符:
import { formatQuery } from 'react-querybuilder'; // 调用formatQuery时传入自定义转换规则 const formattedQuery = formatQuery(query, 'jsonlogic', { operatorTransform: (operator, field, value, valueSource) => { // 针对不同的自定义运算符返回对应的json-logic结构 switch (operator.name) { case 'lengthequals': return { lengthequals: [{ var: field }, Number(value)] }; case 'lengthgreaterthan': return { lengthgreaterthan: [{ var: field }, Number(value)] }; case 'lengthlessthan': return { lengthlessthan: [{ var: field }, Number(value)] }; // 对于默认运算符,返回undefined让默认逻辑处理 default: return undefined; } } });
最后验证
当你用上面任意一种方法修改后,formatQuery应该会生成包含自定义运算符的json-logic结构,类似这样:
{ "and": [ { "lengthgreaterthan": [{ "var": "FirstName" }, 4] }, { ">": [{ "var": "Age" }, 18] } ] }
再结合你之前给json-logic注册的运算逻辑,执行这个结构就能得到正确的结果了。
内容来源于stack exchange

