Flutter信号管理插件preact_signals的使用

发布于 1周前 作者 sinazl 来自 Flutter

Flutter信号管理插件 preact_signals 的使用

preact_signals 是一个完整的 Dart 移植版的 Preact.js Signals。它提供了一种简洁的方式来管理应用程序的状态和信号。

快速入门

该库提供了四个核心函数,这些函数是构建任何业务逻辑的基础:

signal(initialValue)

signal 函数创建一个新的信号。信号是一个容器,可以随着时间改变其值。你可以通过访问 .value 属性来读取或写入信号的值。

import 'package:preact_signals/preact_signals.dart';

final counter = signal(0);

// 读取信号值,输出:0
print(counter.value);

// 写入信号值
counter.value = 1;

signal.peek()

在某些情况下,你可能希望在一个效果中基于前一个值写入另一个信号,但你不希望这个效果订阅该信号。这时可以使用 signal.peek() 来读取信号的前一个值。

final counter = signal(0);
final effectCount = signal(0);

effect(() {
    print(counter.value);

    // 每次触发效果时增加 `effectCount`
    // 但我们不希望这个信号对 `effectCount` 反应
    effectCount.value = effectCount.peek() + 1;
});

untracked(fn)

如果你接收了一个回调函数,并且该回调函数可能会读取一些信号,但你不希望订阅这些信号,可以使用 untracked 来防止订阅发生。

final counter = signal(0);
final effectCount = signal(0);
final fn = () => effectCount.value + 1;

effect(() {
    print(counter.value);

    // 每次触发效果时运行 `fn` 并给出新值
    effectCount.value = untracked(fn);
});

computed(fn)

数据通常由其他现有的数据派生而来。computed 函数允许你将多个信号的值组合成一个新的信号,该信号可以被反应或用于额外的计算。当计算回调中访问的信号发生变化时,计算回调会被重新执行,并返回新的值作为计算信号的值。

import 'package:preact_signals/preact_signals.dart';

final name = signal("Jane");
final surname = signal("Doe");

final fullName = computed(() => "${name.value} ${surname.value}");

// 输出:Jane Doe
print(fullName.value);

// 更新流经计算信号,但只有在有人订阅时才会生效
name.value = "John";
// 输出:John Doe
print(fullName.value);

effect(fn)

effect 函数是使一切变得反应式的关键部分。当你在 effect 回调函数中访问一个信号时,该信号及其所有依赖项都会被激活并订阅。默认情况下,所有更新都是懒加载的,因此直到你在 effect 中访问信号之前,不会有任何更新。

import 'package:preact_signals/preact_signals.dart';

final name = signal("Jane");
final surname = signal("Doe");
final fullName = computed(() => "${name.value} ${surname.value}");

// 输出:Jane Doe
effect(() => print(fullName.value));

// 更新其中一个依赖项会自动触发上面的效果,并输出 John Doe 到控制台
name.value = "John";

batch(fn)

batch 函数允许你将多个信号写操作合并为一个单一的更新,在回调完成后触发。

import 'package:preact_signals/preact_signals.dart';

final name = signal("Jane");
final surname = signal("Doe");
final fullName = computed(() => "${name.value} ${surname.value}");

// 输出:Jane Doe
effect(() => print(fullName.value));

// 将两个信号写操作合并为一个更新
// 在回调返回后,效果将触发并输出 Foo Bar
batch(() {
    name.value = "Foo";
    surname.value = "Bar";
});

完整示例 Demo

以下是一个完整的示例,展示了如何使用 preact_signals 管理状态和信号:

import 'package:flutter/material.dart';
import 'package:preact_signals/preact_signals.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  [@override](/user/override)
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final counter = signal(0);
  final name = signal("Jane");
  final surname = signal("Doe");
  final fullName = computed(() => "${name.value} ${surname.value}");

  [@override](/user/override)
  void initState() {
    super.initState();

    // 监听 fullName 变化并打印到控制台
    effect(() => print(fullName.value));
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Preact Signals Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('You have pushed the button this many times:'),
            Text(
              '${counter.value}',
              style: Theme.of(context).textTheme.headline4,
            ),
            TextField(
              onChanged: (value) => name.value = value,
              decoration: InputDecoration(labelText: 'First Name'),
            ),
            TextField(
              onChanged: (value) => surname.value = value,
              decoration: InputDecoration(labelText: 'Last Name'),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => counter.value++,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

更多关于Flutter信号管理插件preact_signals的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter信号管理插件preact_signals的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用preact_signals插件进行信号管理的代码示例。请注意,preact_signals并非一个广泛认知的Flutter插件,所以我将假设它类似于一个用于状态管理和事件传递的库。如果没有一个确切的preact_signals库,以下代码将基于一个通用的信号管理库的概念进行演示。

在实际项目中,你可能需要替换或调整代码以适应具体的preact_signals库(如果存在)的API。

假设的preact_signals库使用示例

首先,确保你已经在pubspec.yaml文件中添加了preact_signals依赖(假设它存在):

dependencies:
  flutter:
    sdk: flutter
  preact_signals: ^x.y.z  # 替换为实际版本号

然后运行flutter pub get来安装依赖。

1. 创建一个信号管理器

假设preact_signals允许你创建一个信号中心来管理不同的事件和状态。

import 'package:preact_signals/preact_signals.dart';

class SignalManager {
  final Signal<String> dataUpdatedSignal = Signal<String>();

  void updateData(String newData) {
    dataUpdatedSignal.emit(newData);
  }
}

2. 在应用中注册监听器

在你的Flutter组件中,你可以注册一个监听器来响应信号。

import 'package:flutter/material.dart';
import 'package:preact_signals/preact_signals.dart';
import 'signal_manager.dart';  // 假设你的信号管理器在这个文件中

void main() {
  final SignalManager signalManager = SignalManager();

  runApp(MyApp(signalManager: signalManager));
}

class MyApp extends StatelessWidget {
  final SignalManager signalManager;

  MyApp({required this.signalManager});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Signal Management Demo'),
        ),
        body: SignalListenerWidget(signalManager: signalManager),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            signalManager.updateData('New Data at ${DateTime.now()}');
          },
          tooltip: 'Update Data',
          child: Icon(Icons.add),
        ),
      ),
    );
  }
}

3. 创建监听信号的组件

创建一个组件来监听并响应信号。

import 'package:flutter/material.dart';
import 'package:preact_signals/preact_signals.dart';
import 'signal_manager.dart';

class SignalListenerWidget extends StatefulWidget {
  final SignalManager signalManager;

  SignalListenerWidget({required this.signalManager});

  @override
  _SignalListenerWidgetState createState() => _SignalListenerWidgetState();
}

class _SignalListenerWidgetState extends State<SignalListenerWidget> {
  String? displayedData;

  @override
  void initState() {
    super.initState();
    widget.signalManager.dataUpdatedSignal.connect((data) {
      setState(() {
        displayedData = data;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text(
            displayedData ?? 'No data yet',
            style: TextStyle(fontSize: 24),
          ),
        ],
      ),
    );
  }
}

说明

  1. SignalManager:负责管理信号,这里创建了一个dataUpdatedSignal信号。
  2. MyApp:应用的主入口,创建了一个SignalManager实例并将其传递给子组件。
  3. SignalListenerWidget:一个监听dataUpdatedSignal信号的组件,当信号被触发时,更新显示的数据。

请注意,上述代码是基于一个假设的preact_signals库编写的。如果preact_signals实际上并不存在,或者它的API与假设的不同,你需要根据实际的库文档进行调整。如果你确实有一个特定的preact_signals库,请参考该库的官方文档来获取正确的使用方法和API。

回到顶部