Skip to content

库与导入

导入和库指令可以帮助你创建模块化且可共享的代码库。库不仅提供API,还是隐私的单元:以下划线(_)开头的标识符仅在库内部可见。每个Dart文件(及其部件)都是一个库,即使它没有使用库指令。

库可以通过包进行分发。

Dart使用下划线而不是像public、protected或private这样的访问修饰符关键字。虽然其他语言的访问修饰符关键字提供了更细粒度的控制,但Dart使用下划线和基于库的隐私提供了一种简单的配置机制,有助于实现高效的动态访问,并改进了摇树优化(死代码消除)。

使用库

使用import指定如何在一个库的作用域中使用另一个库的命名空间。

例如,Dart Web应用程序通常使用dart:js_interop库,可以这样导入:

dart
import 'dart:js_interop';

import唯一必需的参数是指定库的URI。对于内置库,URI具有特殊的dart:方案。对于其他库,你可以使用文件系统路径或package:方案。package:方案指定由包管理器(如pub工具)提供的库。例如:

dart
import 'package:test/test.dart';

注意:URI代表统一资源标识符。URL(统一资源定位符)是URI的一种常见类型。

指定库前缀

如果导入的两个库有冲突的标识符,可以为一个或两个库指定前缀。例如,如果library1和library2都有一个Element类,你可能会有如下代码:

dart
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;

// 使用lib1中的Element
Element element1 = Element();

// 使用lib2中的Element
lib2.Element element2 = lib2.Element();

使用通配符名称_作为导入前缀是非绑定的,但将提供对该库中非私有扩展的访问。

导入库的部分内容

如果你只想使用库的一部分,可以选择性导入库。例如:

dart
// 只导入foo
import 'package:lib1/lib1.dart' show foo;

// 导入除foo外的所有名称
import 'package:lib2/lib2.dart' hide foo;

延迟加载库

延迟加载(也称为懒加载)允许Web应用程序在需要时按需加载库。当你需要满足以下一个或多个需求时,使用延迟加载:

  • 减少Web应用程序的初始启动时间
  • 进行A/B测试 - 例如尝试算法的替代实现
  • 加载很少使用的功能,如可选屏幕和对话框

这并不意味着Dart会在启动时加载所有延迟组件。Web应用程序可以在需要时通过网络下载延迟组件。

dart工具不支持除Web之外的其他目标的延迟加载。如果你正在构建Flutter应用程序,请参阅Flutter指南中关于延迟组件的实现。

要延迟加载库,首先使用deferred as导入它:

dart
import 'package:greetings/hello.dart' deferred as hello;

当你需要该库时,使用库的标识符调用loadLibrary():

dart
Future<void> greet() async {
  await hello.loadLibrary();
  hello.printGreeting();
}

在前面的代码中,await关键字会暂停执行,直到库加载完成。有关async和await的更多信息,请查看异步编程。

你可以多次调用loadLibrary()而不会出现问题。库只会被加载一次。

使用延迟加载时请记住以下几点:

  • 延迟库的常量在导入文件中不是常量。记住,这些常量在延迟库加载之前不存在。
  • 你不能在导入文件中使用延迟库中的类型。相反,考虑将接口类型移动到延迟库和导入文件都导入的库中。
  • Dart会隐式地将loadLibrary()插入到你使用deferred as命名空间定义的命名空间中。loadLibrary()函数返回一个Future。

库指令

要在文件开头指定库级别的文档注释或元数据注解,请将它们附加到库声明上:

dart
/// 一个非常棒的测试库。
@TestOn('browser')
library;

实现库

有关如何实现包的建议,请参阅《创建包》,包括:

  • 如何组织库源代码
  • 如何使用export指令
  • 何时使用part指令
  • 如何使用条件导入和导出来实现支持多个平台的库