update Signals on Flutter

This commit is contained in:
thislight 2023-12-09 21:04:41 +08:00
parent 98a99dc80d
commit 014b4f6dc7
No known key found for this signature in database
GPG key ID: A50F9451AC56A63E

View file

@ -7,7 +7,7 @@ tags:
- 前端开发 - 前端开发
--- ---
最近看到很多在Flutter上实现Signal范式的项目其实我自己也试了一下。感想是Dart缺少太多语法特性了……真正的Signal范式需要很多胶水代码在JS上这些胶水代码都是用代码生成器生成的但是Dart和Flutter让这个生成器不是那么的好写或者没法方便的用自带的特性做类似的功能。 最近看到很多在Flutter上实现Signals范式的项目其实我自己也试了一下。感想是Dart缺少太多语法特性了……真正的Signals范式需要很多胶水代码在JS上这些胶水代码都是用代码生成器生成的但是Dart和Flutter让这个生成器不是那么的好写或者没法方便的用自带的特性做类似的功能。
<!--more--> <!--more-->
@ -30,12 +30,38 @@ createComponent(Hello, {
这样才能做到两个功能: 这样才能做到两个功能:
1. lazy evaluation只有从props里面获取name时才会evaluate相应表达式 1. lazy evaluation只有从props里面获取name时才会evaluate相应表达式
2. 自动依赖跟踪通过模拟一个dynamic-scope variablelazy evaluation可以让signal在被访问时获得这个变量的值来跟踪依赖。这个是最简单而且计算最少的实现方法时间复杂度可以做到常数级 2. 自动依赖跟踪通过模拟一个dynamic-scope variablelazy evaluation可以让signal在被访问时获得这个变量的值来跟踪依赖。这个是最简单而且计算最少的实现方法时间复杂度可以做到常数级
但是在Dart和Flutter Widget里面你很难处理成这样。 但是在Dart和Flutter Widget里面你很难处理成这样。
如果你通过InheritWidget这种来做依赖跟踪它需要在Element树向上查找这个性能损失太大了。Dart也没有好用的proxy范式所以很难简单的实现lazy evaluation。如果你的参数收Signal对象那也是胶水代码的重要来源。 为了理解这个挑战可以考虑一下下面这样的API怎么在Dart和Flutter上实现
```tsx
// 怎么恰当处理组件的类型?
const Hello: Component<{name: string, effectName: string}> = (props) => {
const [isWorld, setIsWorld] = createSignal(false);
createEffect(() => {
if (!isWorld()) {
console.log(props.name); // 如何跟踪这个依赖?
}
});
createEffect(() => {
console.log(props.effectName); // 如何将这个的更新与上面那个区别开?
});
return <div>
<p>Hello, {isWorld() ? "World" : name}</p> {/* 这个表达式该如何处理? */}
<button type="button" onClick={() => setIsWorld(true)}>Toggle</button>
</div>;
};
export default Hello;
```
如果你通过InheritWidget这种来代替dynamic-scope variable做依赖跟踪它需要在Element树向上查找这个性能损失太大了。Dart也没有好用的proxy范式所以很难简单的实现lazy evaluation。如果你的参数收Signal对象那也是胶水代码的重要来源。
Getx虽然很“脏”但是它确实充分发展了Dart和Flutter提供的东西。 Getx虽然很“脏”但是它确实充分发展了Dart和Flutter提供的东西。