最近,我在编写具有自动跟踪功能的Glimmer组件时遇到了来自tracked-toolbox的@cached用例。下面是一个示例代码片段:
import Component from '@glimmer/component';
/**
* Example usage
* <PersonInfo
* @a={{this.objA}}
* @b={{this.stringB}}
* @c={{this.intC}}
* />
* Where objA can be a large object
*/
export default class PersonInfo extends Component {
/**
* I hope @cached here can help avoid re-running output getter in each
* of the other getters, e.g. this.msg, this.link, this.name
* But whenever any input args changes it triggers update
* (i.e. parent run this.objA = newObj)
*/
get output() {
return someExpensiveLogic(this.args.a, this.args.b, this.args.c);
}
get msg() {
return translate(this.output.msg);
}
get link() {
return convert(this.output.link);
}
get name() {
return change(this.output.name);
}
}{{!-- In the template --}}
<div>
{{this.name}}
{{this.msg}}
{{this.link}}
</div>在不使用@cached的情况下,上面的代码将在渲染时执行output getter 3次,分别针对msg、link和name执行一次。
我也考虑过为output构建自己的缓存,但这需要我手动跟踪使用的状态并对它们进行哈希处理,这可能会很昂贵,而且很难维护。
根据我的理解,@cached提供的是对自动跟踪系统中的“全局标记”的访问,因此我可以依靠该标记来确定缓存何时需要刷新。
因为在我目前工作的一个公司项目中不支持这一点,我希望这个用法可以鼓励我们以后添加这样的支持。
注意:我发现@cached是一个很方便的包装器
import { createCache, getValue } from '@glimmer/tracking/primitives/cache';所以从根本上说,我需要的是@glimmer/tracking/primitives/cache。
发布于 2020-09-25 01:22:19
在这里发布基于离线讨论的后续文章。
这是tracked-toolbox中@cached实用程序的有效用法。狭义用例满足以下要求:
output getter的开销很大,output的结果在JS的其他getter中被多次使用。(如果只在模板中直接使用this.output,它在重新运行output getter中使用的值的显式缓存时具有与@cache.)@cache将不会计算参数值的更改,这意味着如果this.args.b设置为与以前相同的值,output getter仍将重新运行。在这个用例中,这不是一个问题,因为我知道父进程不会在输入参数中设置相同的值。https://stackoverflow.com/questions/64051337
复制相似问题