Flutter类型定义插件typings的使用

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

Flutter类型定义插件typings的使用

简介

typings 是一个用于在Flutter项目中使用NPM包的强大工具。它通过读取和转换TypeScript声明文件(.d.ts)到Dart,使得可以直接在Flutter项目中导入和使用JavaScript文件,而无需将其包含在HTML文件中。此外,还可以从非NPM文件生成interop。

安装和配置

要使用 typings 插件,首先需要在 pubspec.yaml 文件中添加依赖:

dependencies:
  typings: ^最新版本

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

使用示例

1. 简单的 console.log 示例

这是一个非常简单的示例,展示了如何使用 typings 插件来调用 JavaScript 的 console.log 方法。

import 'package:typings/core.dart' as js;

void main() {
  js.console.log(['Hello', 'World']);
}
2. 使用 GoJS 库

以下是一个更复杂的示例,展示了如何使用 typings 插件来集成 GoJS 库,并创建一个简单的流程图。

import 'package:typings/d/gojs.dart' as go;

Future<void> makeGo() async {
  void showLinkLabel(go.DiagramEvent e) {
    var label = e.subject.findObject('LABEL');
    if (label == null) {
      label.visible = (e.subject.fromNode.data.category == 'Conditional');
    }
  }

  await go.import(); // 插入 GoJS js 文件到 DOM

  final diagram = go.Diagram.$2('myDiagramDiv')
    ..addDiagramListener(go.DiagramEventNameOptions.linkDrawn, showLinkLabel)
    ..addDiagramListener(
        go.DiagramEventNameOptions.linkRelinked, showLinkLabel);

  // 定义节点样式
  go.Node nodeStyle() => go.Node.$1()
    ..locationSpot = go.Spot.center
    ..bind.$1(
        go.Binding('location', 'loc', ([v, t]) => go.Point.parse(v as String))
            .makeTwoWay((v, [s, m]) => go.Point.stringify(v as go.Point)));

  // 定义文本样式
  go.TextBlock textStyle([String? text]) => go.TextBlock.$1()
    ..font = 'bold 11pt Lato, Helvetica, Arial, sans-serif'
    ..stroke = '#F8F8F8'
    ..text = text ?? '';

  // 定义端口
  go.Shape makePort(String name, go.Spot align, go.Spot spot, dynamic output, dynamic input) {
    var horizontal = align.equals(go.Spot.top) || align.equals(go.Spot.bottom);
    return go.Shape.$1()
      ..fill = 'transparent'
      ..strokeWidth = 0
      ..width = horizontal ? double.nan : 8
      ..height = !horizontal ? double.nan : 8
      ..alignment = align
      ..stretch = (horizontal ? go.GraphObject.horizontal : go.GraphObject.vertical)
      ..portId = name
      ..fromSpot = spot
      ..fromLinkable = output
      ..toSpot = spot
      ..toLinkable = input
      ..cursor = 'pointer'
      ..mouseEnter = (e, port, k) {
        if (!e.diagram.isReadOnly) {
          (port as go.Shape).fill = 'rgba(255,0,255,0.5)';
        }
      }
      ..mouseLeave = (e, port, k) {
        (port as go.Shape).fill = 'transparent';
      };
  }

  // 设置节点模板
  diagram.nodeTemplateMap.add(
      '', // 默认类别
      nodeStyle()
        ..type = go.Panel.table
        ..add([
          go.Panel.$1()
            ..type = go.Panel.auto
            ..add([
              go.Shape.$1()
                ..figure = 'Rectangle'
                ..fill = '#282c34'
                ..stroke = '#00A9C9'
                ..strokeWidth = 3.5
                ..bind.$1(go.Binding('figure', 'figure')),
              textStyle()
                ..margin = 8
                ..maxSize = go.Size(160, double.nan)
                ..wrap = go.TextBlock.wrapFit
                ..editable = true
                ..bind.$1(go.Binding('text').makeTwoWay())
            ]),
          makePort('T', go.Spot.top, go.Spot.topSide, false, true),
          makePort('L', go.Spot.left, go.Spot.leftSide, true, true),
          makePort('R', go.Spot.right, go.Spot.rightSide, true, true),
          makePort('B', go.Spot.bottom, go.Spot.bottomSide, true, false)
        ]));

  // 加载数据
  var load = '''
    { "class": "go.GraphLinksModel",
      "nodeDataArray": [
        {"key":1, "loc":"0 0", "text":"Start"},
        {"key":2, "loc":"150 0", "text":"Step 1"},
        {"key":3, "loc":"300 0", "text":"Step 2"},
        {"key":4, "loc":"450 0", "text":"End"}
      ],
      "linkDataArray": [
        {"from":1, "to":2},
        {"from":2, "to":3},
        {"from":3, "to":4}
      ]
    }
  ''';

  diagram.model = go.Model.fromJson(load);
}

void main() {
  makeGo();
}

添加新的NPM包

要将新的NPM包添加到 typings 中,可以按照以下步骤操作:

  1. 创建文件:在 typings/lib/d/ 目录下创建一个新的 Dart 文件,例如 mypackage.dart
  2. 添加导出:在你的主包文件中(例如 yourpackage/yourpackage.dart),添加对新文件的导出。
  3. 添加注解:在新文件中添加 [@Typings](/user/Typings).npm 注解,以指导插件如何从NPM同步包。

示例:

// 文件: /typings/d/mypackage.dart
import 'package:typings/annotations.dart';

[@Typings](/user/Typings).npm(
    package: 'mypackage', // 包名
    version: '1.0.0', // 版本号
    dirName: 'mypackage', // 创建的目录名
    contextCheck: 'mypackage', // 可选,检查导入时的命名空间
    uses: [
      'core' // 使用的核心类型
    ]
  )
export 'mypackage/mypackage.dart';

更多关于Flutter类型定义插件typings的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter类型定义插件typings的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter项目中,类型定义插件(typings)通常与Dart的类型系统紧密相关。尽管Flutter和Dart本身并不直接依赖TypeScript中的“typings”概念(这是TypeScript中用于类型定义的文件),但我们可以利用Dart的强大类型系统来定义和管理类型。

在Flutter中,类型定义通常通过Dart的类、接口(Dart中没有正式的接口概念,但可以使用抽象类实现类似功能)、typedef和泛型来实现。为了展示如何在Flutter项目中定义和使用类型,以下是一个简单的代码案例:

1. 定义数据类型

首先,我们定义一个简单的用户数据模型。

// user_model.dart
class User {
  final String name;
  final int age;

  User({required this.name, required this.age});

  // 可以添加其他方法或属性
  String get greeting => 'Hello, my name is $name and I am $age years old.';
}

2. 使用抽象类或接口模拟

假设我们有一个数据服务接口,用于获取用户数据。在Dart中,我们可以使用抽象类来实现这一点。

// user_service.dart
abstract class UserService {
  Future<User> getUserById(int id);
}

3. 实现接口(抽象类)

接下来,我们实现一个具体的用户服务类。

// mock_user_service.dart
import 'dart:async';
import 'user_model.dart';
import 'user_service.dart';

class MockUserService implements UserService {
  @override
  Future<User> getUserById(int id) async {
    // 模拟从API获取用户数据
    await Future.delayed(Duration(seconds: 1)); // 模拟网络延迟
    return User(name: 'John Doe', age: 30);
  }
}

4. 使用类型定义

现在,我们可以在Flutter应用中使用这个服务来获取用户数据,并展示给用户。

// main.dart
import 'package:flutter/material.dart';
import 'user_model.dart';
import 'mock_user_service.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: UserProfilePage(),
    );
  }
}

class UserProfilePage extends StatefulWidget {
  @override
  _UserProfilePageState createState() => _UserProfilePageState();
}

class _UserProfilePageState extends State<UserProfilePage> {
  late User user;
  late Future<User> futureUser;

  @override
  void initState() {
    super.initState();
    final userService = MockUserService();
    futureUser = userService.getUserById(1);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('User Profile'),
      ),
      body: Center(
        child: FutureBuilder<User>(
          future: futureUser,
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.done) {
              if (snapshot.hasError) {
                return Text('Error: ${snapshot.error}');
              } else {
                user = snapshot.data!;
                return Text(user.greeting);
              }
            } else {
              return CircularProgressIndicator();
            }
          },
        ),
      ),
    );
  }
}

总结

在Flutter中,虽然没有直接的“typings”文件(如TypeScript中的.d.ts文件),但我们可以通过Dart的类、抽象类和泛型等特性来定义和管理类型。上面的代码案例展示了如何在Flutter项目中定义用户模型、服务接口和实现,并在UI中使用这些类型定义。这种结构化的类型管理方式有助于提升代码的可读性、可维护性和可扩展性。

回到顶部