让数据随 Flutter 一起飞翔
Dart[^1] + Flutter[^2] 是一种流行的跨平台应用框架。JavaScript 代码可以通过 嵌入式引擎 运行。
¥Dart[^1] + Flutter[^2] is a popular cross-platform app framework. JavaScript code can be run through embedded engines.
SheetJS 是一个用于从电子表格读取和写入数据的 JavaScript 库。
¥SheetJS is a JavaScript library for reading and writing data from spreadsheets.
该演示使用 Dart + Flutter 和 SheetJS 来处理电子表格。我们将探讨如何使用 flutter_js
包运行 JavaScript 代码以及如何在 Dart 代码和特定于平台的 JS 引擎之间传递数据。
¥This demo uses Dart + Flutter and SheetJS to process spreadsheets. We'll explore
how to use the flutter_js
package to run JavaScript code and how to pass data
between Dart code and the platform-specific JS engines.
"演示" 创建一个应用,如下图所示:
¥The "Demo" creates an app that looks like the screenshots below:
iOS | Android |
---|---|
本 demo 在以下环境下进行了测试:
¥This demo was tested in the following environments:
真实设备
¥Real Devices
OS | 设备 | Dart | Flutter | 日期 |
---|---|---|---|---|
安卓 30 | 英伟达盾 | 3.4.3 | 3.22.2 | 2024-06-09 |
iOS 15.1 | iPad Pro | 3.4.3 | 3.22.2 | 2024-06-09 |
模拟器
¥Simulators
OS | 设备 | Dart | Flutter | 开发平台 | 日期 |
---|---|---|---|---|---|
安卓 34 | 像素 3a | 3.4.3 | 3.22.2 | darwin-x64 | 2024-06-09 |
iOS 17.5 | iPhone 15 Pro 最大 | 3.4.3 | 3.22.2 | darwin-x64 | 2024-06-09 |
Android 35 | 像素 3a | 3.5.0 | 3.24.0 | win11-x64 | 2024-08-10 |
在开始此演示之前,请手动禁用遥测。在 MacOS 上:
¥Before starting this demo, manually disable telemetry. On MacOS:
dart --disable-telemetry
dart --disable-analytics
flutter config --no-analytics
flutter config --disable-telemetry
集成详情
¥Integration Details
此演示假设你熟悉 Dart 和 Flutter。
¥This demo assumes familiarity with Dart and Flutter.
对于 iOS 和 Android 目标,flutter_js
package[^3] 分别封装 JavaScriptCore[^4] 和 QuickJS[^5] 引擎。
¥For the iOS and Android targets, the flutter_js
package[^3] wraps JavaScriptCore[^4]
and QuickJS[^5] engines respectively.
SheetJS 独立脚本 可以在封装引擎中进行解析和评估。
¥The SheetJS Standalone scripts can be parsed and evaluated in the wrapped engines.
加载 SheetJS
¥Loading SheetJS
添加脚本
¥Adding the scripts
pubspec.yaml
中的 flutter.assets
属性指定资源。假设独立脚本和填充程序放置在 scripts
文件夹中,以下代码片段将脚本加载为资源:
¥The flutter.assets
property in pubspec.yaml
specifies assets. Assuming the
standalone script and shim are placed in the scripts
folder, the following
snippet loads the scripts as assets:
flutter:
assets:
- scripts/xlsx.full.min.js
- scripts/shim.min.js
加载后,可以使用 rootBundle.loadString
加载内容:
¥Once loaded, the contents can be loaded with rootBundle.loadString
:
import 'package:flutter/services.dart' show rootBundle;
String shim = await rootBundle.loadString("scripts/shim.min.js");
String sheetjs = await rootBundle.loadString("scripts/xlsx.full.min.js");
初始化
¥Initialization
强烈建议将引擎添加到 StatefulWidget
状态:
¥It is strongly recommended to add the engine to the state of a StatefulWidget
:
import 'package:flutter_js/flutter_js.dart';
class SheetJSFlutterState extends State<SheetJSFlutter> {
late JavascriptRuntime _engine;
void initState() {
_engine = getJavascriptRuntime();
}
}
运行 SheetJS 脚本
¥Running SheetJS Scripts
由于获取资源是异步的,因此建议创建一个封装器 async
函数并顺序等待每个脚本:
¥Since fetching assets is asynchronous, it is recommended to create a wrapper
async
function and sequentially await each script:
class SheetJSFlutterState extends State<SheetJSFlutter> {
String _version = '0.0.0';
late JavascriptRuntime _engine;
void initState() {
_engine = getJavascriptRuntime();
_initEngine(); // note: this is not `await`-ed
}
Future<void> _initEngine() async {
/* fetch and evaluate the shim */
String shim = await rootBundle.loadString("scripts/shim.min.js");
_engine.evaluate(shim);
/* fetch and evaluate the main script */
String sheetjs = await rootBundle.loadString("scripts/xlsx.full.min.js");
_engine.evaluate(sheetjs);
/* capture the version string */
JsEvalResult vers = _engine.evaluate("XLSX.version");
setState(() => _version = vers.stringResult);
}
}
读取数据
¥Reading data
下图描绘了练习册华尔兹:
¥The following diagram depicts the workbook waltz:
Dart 中最常见的二进制数据类型是 Uint8List
。它是 http.Response#bodyBytes
的数据类型和 File#readAsBytes()
的返回类型。
¥The most common binary data type in Dart is Uint8List
. It is the data type
for http.Response#bodyBytes
and the return type of File#readAsBytes()
.
Flutter JS 连接器不为 Uint8List
数据提供简单的互操作。在解析之前,应使用 base64Encode
将数据转换为 Base64。
¥The Flutter JS connector offers no simple interop for Uint8List
data. The data
should be converted to Base64 using base64Encode
before parsing.
一旦传递到 JS 引擎,SheetJS read
函数 [^6] 就可以读取 Base64 编码的字符串,而 sheet_to_csv
实用函数 [^7] 可以从工作表生成 CSV 字符串。可以将该字符串拉回到 Dart 代码中。
¥Once passed into the JS engine, the SheetJS read
function[^6] can read the
Base64-encoded string and the sheet_to_csv
utility function[^7] can generate
a CSV string from a worksheet. This string can be pulled back into Dart code.
csv
包提供了一个特殊的 CsvToListConverter
转换器来生成 List<List<dynamic>>
(Dart 的精神上相当于数组的数组)。
¥The csv
package provides a special CsvToListConverter
converter to generate
List<List<dynamic>>
(Dart's spiritual equivalent of the array of arrays).
以下代码片段从 Dart Uint8List
生成 List<List<dynamic>>
:
¥The following snippet generates List<List<dynamic>>
from a Dart Uint8List
:
import 'dart:convert';
import 'package:csv/csv.dart';
class SheetJSFlutterState extends State<SheetJSFlutter> {
List<List<dynamic>> _data = [];
late JavascriptRuntime _engine;
void _processBytes(Uint8List bytes) {
String base64 = base64Encode(bytes);
JsEvalResult func = _engine.evaluate("""
var wb = XLSX.read('$base64');
XLSX.utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]]);
""");
String csv = func.stringResult;
setState(() { _data = CsvToListConverter(eol: "\n").convert(csv); });
}
}
演示
¥Demo
-
请遵循 Flutter[^8] 的官方 "安装" 说明。
¥Follow the official "Install" instructions for Flutter[^8].
运行 flutter doctor
并确认检查了以下项目:
¥Run flutter doctor
and confirm the following items are checked:
- Linux
- macOS
- Windows
[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0) [✓] Xcode - develop for iOS and macOS (Xcode 15.4)
[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0)
(实际版本号可能有所不同)
¥(the actual version numbers may differ)
Installation Notes (click to hide)
第一次运行时,可能会出现 "Android 工具链" 警告:
¥On first run, there may be a warning with "Android toolchain":
[!] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
! Some Android licenses not accepted. To resolve this, run: flutter doctor
--android-licenses
如上所述,修复方法是运行命令:
¥As stated, the fix is to run the command:
flutter doctor --android-licenses
第一次运行时,可能会出现 "Xcode" 警告:
¥On first run, there may be a warning with "Xcode":
[!] Xcode - develop for iOS and macOS (Xcode 15.0.1)
✗ Unable to get list of installed Simulator runtimes.
在 Xcode 中打开 "设置" 面板。在 "平台" 下,单击 "iOS" 旁边的 "得到"。
¥Open "Settings" panel in Xcode. Under "Platforms", click "Get" next to "iOS".
在本地测试中,Android 工具链存在问题:
¥In local testing, there were issues with the Android toolchain:
error: Android sdkmanager not found. Update to the latest Android SDK and ensure that the cmdline-tools are installed to resolve this.
Android Studio 默认不安装 Android SDK Command-Line Tools
。必须手动安装。
¥Android Studio does not install Android SDK Command-Line Tools
by default. It
must be installed manually.
假设已安装命令行工具
¥Assuming the command-line tools are installed
通过切换到 Java 20、安装 Android SDK 33
并回滚到 Android SDK Command-Line Tools (revision: 10.0)
修复了此问题
¥This was fixed by switching to Java 20, installing Android SDK 33
, and rolling
back to Android SDK Command-Line Tools (revision: 10.0)
如果未安装 Google Chrome,flutter doctor
将显示一个问题:
¥If Google Chrome is not installed, flutter doctor
will show an issue:
[✗] Chrome - develop for the web (Cannot find Chrome executable at
/Applications/Google Chrome.app/Contents/MacOS/Google Chrome)
! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable.
如果安装了 Chromium,则应手动分配环境变量:
¥If Chromium is installed, the environment variable should be manually assigned:
- Linux
- macOS
- Windows
CHROME_EXECUTABLE
环境变量应设置为 chrome
二进制文件的路径。此路径在发行版和包管理器之间有所不同。
¥The CHROME_EXECUTABLE
environment variable should be set to the path to the
chrome
binary. This path differs between distributions and package managers.
export CHROME_EXECUTABLE=/Applications/Chromium.app/Contents/MacOS/Chromium
在搜索栏中输入 env
,然后选择 "编辑系统环境变量"。
¥Type env
in the search bar and select "Edit the system environment variables".
在新窗口中,单击 "环境变量..." 按钮。
¥In the new window, click the "Environment Variables..." button.
在新窗口中,查找 "系统变量" 部分并单击 "新的..."
¥In the new window, look for the "System variables" section and click "New..."
将 "变量名" 设置为 CHROME_EXECUTABLE
,并将值设置为程序的路径。上次测试此演示时,在 C:\Users\USERNAME\AppData\Local\Chromium\Application\chrome.exe
为本地用户安装了 Chromium。
¥Set the "Variable name" to CHROME_EXECUTABLE
and the value to the path to the
program. When this demo was last tested, Chromium was installed for the local
user at C:\Users\USERNAME\AppData\Local\Chromium\Application\chrome.exe
.
在每个窗口(3 个窗口)中单击 "OK",然后重新启动计算机。
¥Click "OK" in each window (3 windows) and restart your computer.
运行 flutter emulators
并查找 android
和(仅在 macOS 上)ios
模拟器。
¥Run flutter emulators
and look for android
and (on macOS only) ios
emulators.
- Linux
- macOS
- Windows
Id • Name • Manufacturer • Platform
Pixel_3a_API_35 • Pixel 3a API 35 • Google • android
Id • Name • Manufacturer • Platform
apple_ios_simulator • iOS Simulator • Apple • ios
Pixel_3a_API_34 • Pixel 3a API 34 • Google • android
Id • Name • Manufacturer • Platform
Pixel_3a_API_35 • Pixel 3a API 35 • Google • android
-
禁用遥测。以下命令已确认有效:
¥Disable telemetry. The following commands were confirmed to work:
dart --disable-telemetry
dart --disable-analytics
flutter config --no-analytics
基础项目
¥Base Project
-
创建一个新的 Flutter 项目:
¥Create a new Flutter project:
flutter create sheetjs_flutter
cd sheetjs_flutter
-
启动 Android 模拟器。
¥Start the Android emulator.
Details (click to hide)
安卓工作室
¥Android Studio
在 Android Studio 中,单击 "更多操作" > "虚拟设备管理器"。在列表中查找模拟设备,然后单击 ▶ 按钮进行播放。
¥In Android Studio, click "More actions" > "Virtual Device Manager". Look for the emulated device in the list and click the ▶ button to play.
命令行
¥Command Line
列出带有 flutter emulators
的可用模拟器:
¥List the available emulators with flutter emulators
:
% flutter emulators
2 available emulators:
apple_ios_simulator • iOS Simulator • Apple • ios
Pixel_3a_API_34 • Pixel 3a API 34 • Google • android
^^^^^^^^^^^^^^^--- the first column is the name
第一列显示应传递给 emulator -avd
的名称。在之前的测试中,名称为 Pixel_3a_API_34
,启动命令为:
¥The first column shows the name that should be passed to emulator -avd
. In a
previous test, the name was Pixel_3a_API_34
and the launch command was:
emulator -avd Pixel_3a_API_34
在 macOS 上,~/Library/Android/sdk/emulator/
是 emulator
二进制文件的典型位置。如果找不到,则将该文件夹添加到 PATH
:
¥On macOS, ~/Library/Android/sdk/emulator/
is the typical location for the
emulator
binary. If it cannot be found, add the folder to PATH
:
export PATH="$PATH":~/Library/Android/sdk/emulator
emulator -avd Pixel_3a_API_34
-
当 Android 模拟器打开时,启动应用:
¥While the Android emulator is open, start the application:
flutter run
If emulator is not detected (click to show)
In some test runs, flutter run
did not automatically detect the emulator.
Run flutter -v -d sheetjs run
and the command will fail. Inspect the output:
[ +6 ms] No supported devices found with name or id matching 'sheetjs'.
[ ] The following devices were found:
...
[ +26 ms] sdk gphone64 arm64 (mobile) • emulator-5554 • android-arm64 • Android 13 (API 33) (emulator)
[ ] macOS (desktop) • macos • darwin-arm64 • macOS 13.5.1 22G90 darwin-arm64
...
Search the output for sheetjs
. After that line, search for the emulator list.
One of the lines will correspond to the running emulator:
[ +26 ms] sdk gphone64 arm64 (mobile) • emulator-5554 • android-arm64 • Android 13 (API 33) (emulator)
^^^^^^^^^^^^^--- the second column is the name
The second column is the device name. Assuming the name is emulator-5554
, run:
flutter -v -d emulator-5554 run
应用加载后,停止终端进程并关闭模拟器。
¥Once the app loads, stop the terminal process and close the simulator.
-
安装 Flutter/Dart 依赖:
¥Install Flutter / Dart dependencies:
flutter pub add http csv flutter_js
该命令可能会在 Windows 中失败,并显示以下消息:
¥The command may fail in Windows with the followimg message:
Building with plugins requires symlink support.
Please enable Developer Mode in your system settings. Run start ms-settings:developers to open settings.
如上所述,必须启用 "开发者模式":
¥As stated, "Developer Mode" must be enabled:
-
运行
start ms-settings:developers
¥Run
start ms-settings:developers
-
在面板中,启用 "开发者模式" 并在弹出窗口中单击 "是的"。
¥In the panel, enable "Developer Mode" and click "Yes" in the popup.
-
重新安装依赖:
¥Reinstall dependencies:
flutter pub add http csv flutter_js
-
用文本编辑器打开
pubspec.yaml
。搜索以flutter:
开头的行(无空格)并添加高亮的行:¥Open
pubspec.yaml
with a text editor. Search for the line that starts withflutter:
(no whitespace) and add the highlighted lines:
# The following section is specific to Flutter packages.
flutter:
assets:
- scripts/xlsx.full.min.js
- scripts/shim.min.js
-
下载依赖到
scripts
文件夹:¥Download dependencies to the
scripts
folder:
mkdir -p scripts
cd scripts
curl -LO https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/xlsx.full.min.js
curl -LO https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/shim.min.js
cd ..
PowerShell curl
与官方 curl
程序不兼容。该命令可能会因参数错误而失败:
¥PowerShell curl
is incompatible with the official curl
program. The command
may fail with a parameter error:
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
必须改用 curl.exe
:
¥curl.exe
must be used instead:
mkdir -p scripts
cd scripts
curl.exe -LO https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/xlsx.full.min.js
curl.exe -LO https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/shim.min.js
cd ..
curl -L -o lib/main.dart https://xlsx.nodejs.cn/flutter/main.dart
PowerShell curl
与官方 curl
程序不兼容。该命令可能会因参数错误而失败:
¥PowerShell curl
is incompatible with the official curl
program. The command
may fail with a parameter error:
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'L'.
必须改用 curl.exe
:
¥curl.exe
must be used instead:
curl.exe -L -o lib/main.dart https://xlsx.nodejs.cn/flutter/main.dart
安卓
¥Android
-
使用与步骤 3 相同的说明启动 Android 模拟器。
¥Start the Android emulator using the same instructions as Step 3.
-
启动应用:
¥Launch the app:
flutter run
该应用获取 https://xlsx.nodejs.cn/pres.numbers,解析数据,将数据转换为数组数组,并将数据渲染在 Flutter Table
小部件中。
¥The app fetches https://xlsx.nodejs.cn/pres.numbers, parses, converts data to
an array of arrays, and presents the data in a Flutter Table
widget.
If emulator is not detected (click to show)
In some test runs, flutter run
did not automatically detect the emulator.
Run flutter -v -d sheetjs run
and the command will fail. Inspect the output:
[ +6 ms] No supported devices found with name or id matching 'sheetjs'.
[ ] The following devices were found:
...
[ +26 ms] sdk gphone64 arm64 (mobile) • emulator-5554 • android-arm64 • Android 13 (API 33) (emulator)
[ ] macOS (desktop) • macos • darwin-arm64 • macOS 13.5.1 22G90 darwin-arm64
...
Search the output for sheetjs
. After that line, search for the emulator list.
One of the lines will correspond to the running emulator:
[ +26 ms] sdk gphone64 arm64 (mobile) • emulator-5554 • android-arm64 • Android 13 (API 33) (emulator)
^^^^^^^^^^^^^--- the second column is the name
The second column is the device name. Assuming the name is emulator-5554
, run:
flutter -v -d emulator-5554 run
在一些演示运行中,构建失败并出现 Android SDK 错误:
¥In some demo runs, the build failed with an Android SDK error:
│ The plugin flutter_js requires a higher Android SDK version. │
│ Fix this issue by adding the following to the file /.../android/app/build.gradle: │
│ android { │
│ defaultConfig { │
│ minSdkVersion 21 │
│ } │
│ } │
通过编辑 android/app/build.gradle
已修复此问题。
¥This was fixed by editing android/app/build.gradle
.
搜索 minSdkVersion
应显示以下行:
¥Searching for minSdkVersion
should reveal the following line:
minSdkVersion flutter.minSdkVersion
flutter.minSdkVersion
应替换为 21
:
¥flutter.minSdkVersion
should be replaced with 21
:
minSdkVersion 21
-
关闭 Android 模拟器。
¥Close the Android emulator.
iOS
-
启动 iOS 模拟器。
¥Start the iOS simulator.
-
启动应用:
¥Launch the app:
flutter run
该应用获取 https://xlsx.nodejs.cn/pres.numbers,解析数据,将数据转换为数组数组,并将数据渲染在 Flutter Table
小部件中。
¥The app fetches https://xlsx.nodejs.cn/pres.numbers, parses, converts data to
an array of arrays, and presents the data in a Flutter Table
widget.
安卓设备
¥Android Device
-
使用 USB 电缆连接 Android 设备。
¥Connect an Android device using a USB cable.
如果设备要求允许 USB 调试,请点击 "允许"。
¥If the device asks to allow USB debugging, tap "Allow".
-
验证
flutter
是否可以找到该设备:¥Verify that
flutter
can find the device:
flutter devices
该列表应包括设备:
¥The list should include the device:
SheetJS (mobile) • 726272627262726272 • android-arm64 • Android 11 (API 30)
^^^^^^^--- the first column is the name
-
构建 APK:
¥Build an APK:
flutter build apk --release
-
在 Android 设备上安装:
¥Install on the Android device:
flutter install
脚本可能会要求一个设备:
¥The script may ask for a device:
[1]: SheetJS (1234567890)
[2]: iPhone 15 Pro Max (12345678-9ABC-DEF0-1234-567890ABCDEF)
[3]: macOS (macos)
[4]: Chrome (chrome)
Please choose one (or "q" to quit):
选择设备对应的编号。
¥Select the number corresponding to the device.
-
在设备上启动已安装的
sheetjs_flutter
应用。¥Launch the installed
sheetjs_flutter
app on the device.
应用可能需要 30 秒才能加载内容。
¥The app may take 30 seconds to load the content.
Android 12[^9] 中的 Dart HTTP 客户端存在已知错误。
¥There are known bugs in the Dart HTTP client in Android 12[^9].
iOS 设备
¥iOS Device
-
遵循官方 "部署到物理 iOS 设备" 说明 [^10]
¥Follow the official "Deploy to physical iOS devices" instructions[^10]
-
连接 iOS 设备并验证
flutter
可以找到该设备:¥Connect the iOS device and verify that
flutter
can find the device:
flutter devices
该列表应包括设备:
¥The list should include the device:
SheetPad (mobile) • 00000000-0000000000000000 • ios • iOS 15.1 19B74
^^^^^^^^--- the first column is the name
-
在设备上运行程序:
¥Run the program on the device:
flutter run -d SheetPad
在调试模式下,"Flutter 工具" 将尝试连接到正在运行的应用。设备将请求权限:
¥In debug mode, "Flutter tools" will attempt to connect to the running app. The device will ask for permission:
"Sheetjs Flutter" 希望查找并连接到本地网络上的设备。
¥"Sheetjs Flutter" would like to find and connect to devices on your local network.
点击 "OK" 继续。
¥Tap "OK" to continue.
上次测试此演示时,构建失败并出现错误:
¥When this demo was last tested, the build failed with an error:
Could not build the precompiled application for the device.
Error (Xcode): No profiles for 'com.example.sheetjsFlutter' were found: Xcode couldn't find any iOS App Development provisioning profiles matching 'com.example.sheetjsFlutter'. Automatic signing is disabled and unable to generate a profile. To enable automatic signing, pass -allowProvisioningUpdates to xcodebuild.
消息包含提示:
¥The message includes a hint:
Verify that the Bundle Identifier in your project is your signing id in Xcode
open ios/Runner.xcworkspace
打开工作区并在导航器中选择 "Runner" 项目。在主窗格中,选择 "签名和能力" 并确保选择了团队。从菜单栏中,选择 "产品" > "运行" 以运行应用。
¥Open the workspace and select the "Runner" project in the Navigator. In the main pane, select "Signing & Capabilities" and ensure a Team is selected. From the menu bar, select "Product" > "Run" to run the app.
如果出现 "不受信任的开发者" 错误,则必须在设备上信任证书。以下步骤已在 iOS 15.1 中得到验证:
¥If there is an "Untrusted Developer" error, the certificate must be trusted on the device. The following steps were verified in iOS 15.1:
-
在设备上打开 "设置" 应用
¥Open the "Settings" app on the device
在新屏幕的 "APPS FROM DEVELOPER" 部分中,应显示 "Sheetjs Flutter"。如果缺少,请点击屏幕顶部附近的 "<" 按钮并从列表中选择其他证书。
¥In the "APPS FROM DEVELOPER" section of the new screen, "Sheetjs Flutter" should be displayed. If it is missing, tap the "<" button near the top of the screen and select a different certificate from the list.
-
选择 "一般的" > "VPN 和设备管理"。
¥Select "General" > "VPN & Device Management".
-
在 "DEVELOPER APP" 部分中,点击证书 "不受信任"。
¥In the "DEVELOPER APP" section, tap the certificate that is "Not Trusted".
-
确认 "Sheetjs Flutter" 在列表中后,点击 "相信" 按钮,然后点击弹出窗口中的 "相信"。
¥After confirming "Sheetjs Flutter" is in the list, tap the "Trust" button and tap "Trust" in the popup.
[^1]: https://dart.dev/ 是 Dart 编程语言的官方网站。
¥https://dart.dev/ is the official site for the Dart Programming Language.
[^2]: https://flutter.dev/ 是 Flutter 框架的官方网站。
¥https://flutter.dev/ is the official site for the Flutter Framework.
[^3]: flutter_js
包 托管在 Dart 包存储库上。
¥The flutter_js
package is hosted on the Dart package repository.
[^4]: 详细信息请参见 专用 "Swift + JavaScriptCore" 演示。
¥See the dedicated "Swift + JavaScriptCore" demo for more details.
[^5]: 详细信息请参见 专用 "C + QuickJS" 演示。
¥See the dedicated "C + QuickJS" demo for more details.
[^6]: 见 read
于 "读取文件"
[^7]: 见 sheet_to_csv
于 "CSV 和文本"
¥See sheet_to_csv
in "CSV and Text"
[^8]: 见 Flutter 安装说明
¥See the Flutter Installation Instructions
[^9]: 例如,http
存储库中的问题 836 提到 API 调用可能需要 10 秒以上。这是 Dart + Flutter 中的一个问题。
¥For example, Issue 836 in the http
repository mentions that API calls may take 10+ seconds. This is an issue in Dart + Flutter.
[^10]: 请参阅 Flutter 文档中的 "部署到物理 iOS 设备"
¥See "Deploy to physical iOS devices" in the Flutter documentation