如何在SurveyJS中限制表达式仅依赖值变更时重评估?
解决SurveyJS自定义函数不必要重渲染与惰性求值问题
问题1:无参数自定义函数(如uuid())被无关字段触发重评估
SurveyJS默认会在任意字段值变化时重新计算所有表达式,除非明确指定函数的依赖项。对于无参数的uuid(),需在注册时标记它不依赖任何字段:
import { FunctionFactory } from "survey-core"; FunctionFactory.Instance.register("uuid", () => { return crypto.randomUUID(); }, { // 明确声明函数无依赖字段 getDependencies: () => [], // 标记函数非确定性(每次调用结果不同) isDeterministic: false });
配置后,只有audit_id字段自身的触发条件(如手动重置)会触发uuid()重新执行,修改audit_type等无关字段不会引发重计算。
问题2:带参数自定义函数被无关字段触发调用
对于带参数的findServiceByModel(),需让函数明确返回它依赖的字段名,SurveyJS会仅在依赖字段变化时重新计算:
FunctionFactory.Instance.register("findServiceByModel", async (modelValue) => { // 你的异步逻辑:根据modelValue获取service const response = await fetch(`/api/services?model=${modelValue}`); return response.json(); }, { // 返回函数依赖的字段名数组 getDependencies: (args) => { // 此处参数对应表达式中的{model},因此依赖字段为"model" return ["model"]; }, isAsync: true // 标记为异步函数 });
注册后,只有model字段值变化时才会重新调用findServiceByModel(),修改audit_type等无关字段不会触发函数执行。
问题3:iif()中函数无条件执行(惰性求值缺失)
SurveyJS原生iif()是贪婪求值逻辑,会先执行所有参数表达式再判断条件。解决方法是自定义支持惰性求值的条件函数,仅在条件满足时执行目标函数:
步骤1:注册惰性条件函数
FunctionFactory.Instance.register("lazyIif", (condition, trueCallback, falseCallback) => { if (condition) { // 仅当条件为真时执行true回调 return typeof trueCallback === "function" ? trueCallback() : trueCallback; } else { // 条件为假时执行false回调 return typeof falseCallback === "function" ? falseCallback() : falseCallback; } }, { getDependencies: (args) => { // 收集条件字段及回调函数中的依赖项 const deps = []; // 提取条件中的依赖字段(如enable_model) if (args[0]?.dependencies) { deps.push(...args[0].dependencies.map(d => d.name)); } // 提取true回调中的依赖字段(如model) if (args[1]?.dependencies) { deps.push(...args[1].dependencies.map(d => d.name)); } return [...new Set(deps)]; // 去重处理 } });
步骤2:修改SurveyJS表达式配置
将原有iif替换为自定义的lazyIif,并将函数调用包装成箭头函数实现延迟执行:
{ "type": "expression", "name": "service", "expression": "lazyIif({enable_model} == true, () => findServiceByModel({model}), () => 'null')" }
配置后,当enable_model为false时,findServiceByModel()不会被执行,仅在条件为真时触发调用。
内容的提问来源于stack exchange,提问作者Kalpadiptya Roy
相关产品推荐
相关产品推荐

