Libraries 库

每个 Dart 文件天然就是一个库,哪怕不写 library 指令;

隐私规则:标识符以 _ 下划线开头 = 库私有,仅当前库内可见,跨文件 / 库无法访问;

public/protected/private 关键字,仅靠下划线区分访问权限;

库可以打包成 package 交给 pub 管理;

优势:利于摇树优化(Tree Shaking),剔除未使用死代码。

import

使用import关键字,来导入其他库。

import 用于引入其他库的 API

URI 分三类:

  1. dart:xxx:Dart 内置标准库(dart:coredart:asyncdart:js_interop
  2. package:xxx:pub 包管理的第三方库
  3. 相对文件路径:本地自定义 .dart 文件
// 内置标准库
import 'dart:js_interop';
import 'dart:math';

// 第三方包
import 'package:test/test.dart';

// 本地文件库
import './utils.dart';Code language: Dart (dart)

库别名

两个库存在同名类 / 函数,用 as 别名 区分隔离。

例如

在 lib1.dart 文件中

class Element {}Code language: JavaScript (javascript)

lib2.dart 中同名类

class Element {}Code language: JavaScript (javascript)

main.dart 主函数文件中

// 直接导入,默认命名空间
import 'lib1.dart';
// 指定别名 lib2
import 'lib2.dart' as lib2;

void main() {
  Element e1 = Element(); // lib1 的 Element
  lib2.Element e2 = lib2.Element(); // lib2 的 Element
}Code language: JavaScript (javascript)

为了防止混淆,给lib2.dart 起了一个别名 lib2 这样,访问它里面的类的时候,只需要带上别名前缀就可以。

选择性导入 show /hide

show:只导入指定名称,其余全部隐藏

// 仅导入 foo,其他变量/类不可用
import 'lib1.dart' show foo;

void main() {
  foo();
  // bar(); // 报错,未show,无法访问
}Code language: JavaScript (javascript)

hide:导入全部,唯独隐藏指定名称

// 导入所有,唯独屏蔽 foo
import 'lib2.dart' hide foo;

void main() {
  bar();
  // foo(); // 报错,被hide屏蔽
}Code language: JavaScript (javascript)

延迟加载 deferred as

仅 Web 平台生效

  • 减少网页首屏加载体积;
  • 加载低频弹窗、可选页面;
  • 按需动态下载代码分片。
  1. 导入格式:import xxx deferred as 命名空间
  2. 调用 命名空间.loadLibrary() 返回 Future,配合 await 等待加载完成
  3. 同一个库多次调用 loadLibrary() 只会加载一次
  4. 限制:延迟库内常量、类型不能在加载前直接使用

完整示例

hello.dart(延迟库)

void printGreeting() {
  print("Hello from deferred library wellcome to foxdevelop.com");
}
Code language: JavaScript (javascript)

main.dart

// 延迟导入,别名 hello
import 'hello.dart' deferred as hello;

Future<void> greet() async {
  // 动态加载库
  await hello.loadLibrary();
  // 加载完成后才能调用内部方法
  hello.printGreeting();
}

void main() async {
  await greet();
}
Code language: JavaScript (javascript)

运行结果:

Hello from deferred library wellcome to foxdevelop.com
Code language: JavaScript (javascript)

这两个文件放在同一个文件夹下面

如果hello.dart 放在其他目录,例如上一层的lib目录里面呢?

例如放在 D:\dartdemo\firstdart\lib 这里面

然后我们的main函数的dart放在D:\dartdemo\firstdart\bin 下面

firstdart/
├─ bin/
│  └─ firstdart.dart       // 程序入口
└─ lib/
   └─ hello.dart      // 延迟加载库Code language: JavaScript (javascript)

则需要这么引入

// ../ 代表上一级目录
import '../lib/hello.dart' deferred as hello;Code language: JavaScript (javascript)

library 库顶层声明

写在文件最顶部,用于添加库文档注释、库级注解(如测试平台限定)。

/// 浏览器端专用测试工具库
@TestOn('browser')
library;
Code language: JavaScript (javascript)

export

导出(封装对外统一 API)

写工具包常用,聚合多个子库,对外只暴露一个导入入口。

文件结构

src/math.dart

int add(int a, int b) => a + b;
int sub(int a, int b) => a - b;
Code language: PHP (php)

src/string.dart

String upper(String s) => s.toUpperCase();
Code language: JavaScript (javascript)

utils.dart(统一导出入口)

export 'src/math.dart';
export 'src/string.dart';
// 隐藏内部私有工具
export 'src/internal.dart' hide helper;
Code language: JavaScript (javascript)

utils.dart 不能直接单独运行 它只是导出聚合文件,里面没有 main() 入口函数,不能 dart run lib/utils.dart

export 的作用

    • 聚合多个 src 子文件的 API;
    • 使用者只需要导入 utils.dart 一个文件,就能拿到所有暴露方法;
    • hide xxx 屏蔽内部工具,封装内部实现,控制对外暴露的 API。

    main.dart 使用

    import 'utils.dart';
    
    void main() {
      print(add(1,2));
      print(upper("dart"));
    }
    Code language: JavaScript (javascript)

    注意

    export/import 只是源码层面导入导出,只要分发 .dart 文件别人就能看源码

    想要隐藏源码,必须不发布 .dart 源码,只发布编译后的二进制快照(Snapshot)。

    快照(Snapshot)是 Dart 编译后的二进制文件,别人无法逆向还原完整可读源码,只能调用暴露的 API。

    这个是其他课程讲解。

    part

    拆分单库多文件

    同一个库拆分多个文件,共享下划线私有标识符,必须配套 part 'xxx.dart' / part of '主文件.dart'

    main_lib.dart(主库文件)

    library; //指明这是一个库
    part 'logic.dart'; //把 logic.dart 合并到当前 main_lib.dart,二者属于同一个
    
    int _secret = 999; // 库私有变量
    Code language: JavaScript (javascript)

    logic.dart(分片文件)

    part of 'main_lib.dart'; //声明我属于 main_lib.dart 这个库,不是独立库。
    
    void printSecret() {
      // 可访问主文件 _secret,同库私有互通
      print(_secret);
    }
    Code language: JavaScript (javascript)

    调用

    import 'main_lib.dart'; //引入主库 不要引入分片库
    
    void main() {
      printSecret(); // 输出 999
    }
    Code language: JavaScript (javascript)

    * 条件导入

    根据平台自动切换不同实现文件

    import 'platform_stub.dart'
        if (dart.library.io) 'platform_mobile.dart'
        if (dart.library.js_interop) 'platform_web.dart';
    Code language: JavaScript (javascript)

    发表回复

    您的邮箱地址不会被公开。 必填项已用 * 标注