Flutter JavaScript执行插件js_script的使用
Flutter JavaScript执行插件js_script的使用
在Flutter中,js_script
是一个强大的插件,允许开发者在Dart代码中执行JavaScript脚本,并实现JavaScript与Dart对象之间的交互。以下是如何使用该插件的详细说明及完整示例。
使用方法
创建 JavaScript 上下文
首先,创建一个 JsScript
对象来管理 JavaScript 的上下文。
JsScript script = JsScript();
定义并注册 Dart 类到 JavaScript
通过 ClassInfo
将 Dart 类映射到 JavaScript,并定义其字段和方法。
var classInfo = ClassInfo<TestClass>(
newInstance: (_) => TestClass(), // 创建实例的方法
fields: {
"field": JsField.ins(
get: (obj) => obj.field, // 获取字段值
set: (obj, val) => obj.field = val, // 设置字段值
),
},
functions: {
"method": JsFunction.ins((obj, argv) => obj.method()), // 调用 Dart 方法
"wait": JsFunction.ins((obj, argv) => obj.wait(argv[0])), // 带参数调用 Dart 方法
}
);
然后将类信息注册到 JavaScript 上下文中:
script.addClass(classInfo);
在 JavaScript 中操作 Dart 对象
可以在 JavaScript 中创建 Dart 对象并调用其方法或修改其属性。
script.eval("var obj = new TestClass()"); // 在 JavaScript 中创建 Dart 对象
test("[JS] obj.field == 1", script.eval("obj.field") == 1); // 检查字段值
test("[JS] obj.method() == 3", script.eval("obj.method()") == 3); // 调用 Dart 方法
在 Dart 中操作 JavaScript 对象
通过 JsValue
可以获取 JavaScript 对象并访问其属性或调用其方法。
JsValue jsValue = script.eval("obj"); // 获取 JavaScript 对象
script.eval("obj.field = 3;"); // 修改 JavaScript 对象的字段
test("[Dart] obj.field == 3", jsValue.dartObject.field == 3); // 验证字段值
test("[Dart] obj.method() == 9", jsValue.dartObject.method() == 9); // 调用 Dart 方法
绑定 Dart 对象到 JavaScript
可以将 Dart 对象绑定到 JavaScript 上下文,并直接在 JavaScript 中操作它。
TestClass obj2 = TestClass(); // 创建 Dart 对象
obj2.field = 4; // 设置初始值
JsValue jsValue = script.bind(obj2, classInfo: classInfo); // 绑定到 JavaScript
test("[JS] obj2.field == 4", jsValue["field"] == 4); // 验证字段值
在 JavaScript 中调用 Dart 函数
可以通过 JsValue
注册 Dart 函数并在 JavaScript 中调用。
JsValue func = script.function((argv) => "hello" + argv[0]); // 注册 Dart 函数
test("[JS] call function", func.call(["world"]) == "helloworld"); // 调用函数
使用 JavaScript Promise 和 Dart Future
JavaScript 的 Promise 可以无缝转换为 Dart 的 Future。
JsValue jsPromise = script.eval("""
new Promise(async function(resolve, reject) {
await obj.wait(3);
resolve("over");
});
""");
var time = DateTime.now();
var res = await jsPromise.asFuture; // 等待 Promise 结果
test("[JS] wait for ${DateTime.now().difference(time).inMilliseconds}ms", res == "over");
支持文件系统
可以加载本地文件或内存中的文件,并在 JavaScript 中运行它们。
JsScript script = JsScript(
fileSystems: [
AsarFileSystem(await data), // 加载 ASAR 文件
MemoryFileSystem({ // 加载内存文件
"/test.js": """
const md5 = require('md5');
module.exports = md5('hello');
"""
})
]
);
var ret = script.run("test.js"); // 运行 JavaScript 文件
自动类型转换
任何 Dart 对象都可以自动转换为 JavaScript 对象,并支持直接调用。
JsValue func = script.eval("""
(function (func, map) {
return func(map["test"])
})
""");
test("[JS] test auto convert ", func.call([(content) {
return content;
}, {"test": 26}]) == 26);
完整示例代码
以下是完整的示例代码,展示了如何使用 js_script
插件执行 JavaScript 脚本并与 Dart 进行交互。
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:js_script/filesystems.dart';
import 'package:js_script/js_script.dart';
import 'package:js_script/types.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
[@override](/user/override)
_MyAppState createState() => _MyAppState();
}
class TestClass {
int field = 1;
int method() => field * 3;
Future<void> wait(int sec) => Future.delayed(Duration(seconds: sec));
}
class _MyAppState extends State<MyApp> {
late List<Widget> children = [];
late Future<ByteData> data;
[@override](/user/override)
void initState() {
super.initState();
data = rootBundle.load("res/npmpack.asar");
}
dispose() {
super.dispose();
}
void addLine(String str) {
print(str);
setState(() {
children.add(Text(str, style: TextStyle(color: Colors.black),));
});
}
void test(String str, bool test) {
addLine("$str ===> ${test ? "OK" : "Error"}");
}
void run() async {
JsScript script = JsScript(
fileSystems: [
AsarFileSystem(await data),
MemoryFileSystem({
"/test.js": """
const md5 = require('md5');
module.exports = md5('hello');
"""
})
]
);
test("1 + 2 = 3", script.eval("1 + 2") == 3);
var classInfo = ClassInfo<TestClass>(
newInstance: (_, __) => TestClass(),
fields: {
"field": JsField.ins(
get: (obj) => obj.field,
set: (obj, val) => obj.field = val,
),
},
functions: {
"method": JsFunction.ins((obj, argv) => obj.method()),
"method2": JsFunction.sta((argv) => 3),
"wait": JsFunction.ins((obj, argv) => obj.wait(argv[0])),
}
);
script.addClass(classInfo);
script.eval("var obj = new TestClass()");
test("[JS] obj.field == 1", script.eval("obj.field") == 1);
test("[JS] obj.method() == 3", script.eval("obj.method()") == 3);
JsValue jsValue = script.eval("obj");
script.eval("obj.field = 3;");
test("[Dart] obj.field == 3", jsValue.dartObject.field == 3);
test("[Dart] obj.method() == 9", jsValue.dartObject.method() == 9);
{
// 测试绑定
TestClass obj2 = TestClass();
obj2.field = 4;
JsValue jsValue = script.bind(obj2, classInfo: classInfo);
test("[JS] obj2.field == 4", jsValue["field"] == 4);
}
{
// 测试函数
JsValue func = script.function((argv) => "hello" + argv[0]);
var obj = func.call(["world"]);
print(obj);
test("[JS] call function", func.call(["world"]) == "helloworld");
}
{
JsValue jsPromise = script.eval("""
new Promise(async function(resolve, reject) {
await obj.wait(3);
resolve("over");
});
""");
var time = DateTime.now();
var res = await jsPromise.asFuture;
test("[JS] wait for ${DateTime.now().difference(time).inMilliseconds}ms", res == "over");
}
{
JsValue main = script.eval("""
(function () {
let ret = 0;
for (let i = 0; i < 1000000; ++i) {
ret += obj.method();
}
return ret;
});
""");
var time = DateTime.now();
var res = main.call();
test("[JS] call dart method 1000000 times, using ${DateTime.now().difference(time).inMilliseconds}ms", res == 9000000);
}
{
var ret = script.eval("""
const md5 = require('md5');
md5('hello');
""");
test("[JS] require md5", ret == '5d41402abc4b2a76b9719d911017c592');
ret = script.run("test.js");
test("[JS] run file in FileSystem", ret == '5d41402abc4b2a76b9719d911017c592');
}
{
JsValue func = script.eval("""
(function (func, map) {
return func(map["test"])
})
""");
test("[JS] test auto convert ", func.call([(content) {
return content;
}, {"test": 26}]) == 26);
}
script.dispose();
}
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: ListView.builder(
itemBuilder: (context, index) {
return children[index];
},
itemCount: children.length,
),
floatingActionButton: FloatingActionButton(
onPressed: run,
child: Icon(Icons.run_circle_outlined),
),
),
);
}
}
更多关于Flutter JavaScript执行插件js_script的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter JavaScript执行插件js_script的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
js_script
是一个 Flutter 插件,允许你在 Flutter 应用中执行 JavaScript 代码。它基于 flutter_webview_plugin
和 flutter_js
实现,提供了一个简单的方式来在 Flutter 应用中运行 JavaScript 代码。
安装 js_script
插件
首先,你需要在 pubspec.yaml
文件中添加 js_script
插件的依赖:
dependencies:
flutter:
sdk: flutter
js_script: ^0.0.1 # 请检查最新版本
然后运行 flutter pub get
来安装依赖。
使用 js_script
插件
1. 导入插件
在你的 Dart 文件中导入 js_script
插件:
import 'package:js_script/js_script.dart';
2. 创建 JsScript
实例
你可以通过 JsScript
类来执行 JavaScript 代码。首先,创建一个 JsScript
实例:
final jsScript = JsScript();
3. 执行 JavaScript 代码
使用 evaluate
方法来执行 JavaScript 代码。这个方法返回一个 Future
,你可以通过 await
来获取执行结果。
void runJavaScript() async {
try {
final result = await jsScript.evaluate('1 + 1');
print('Result: $result'); // 输出: Result: 2
} catch (e) {
print('Error: $e');
}
}
4. 处理异步 JavaScript 代码
如果你的 JavaScript 代码是异步的,你可以使用 Promise
并返回一个值。js_script
插件会自动处理 Promise
并返回其结果。
void runAsyncJavaScript() async {
try {
final result = await jsScript.evaluate('''
new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Hello, Flutter!");
}, 1000);
});
''');
print('Result: $result'); // 输出: Result: Hello, Flutter!
} catch (e) {
print('Error: $e');
}
}
5. 传递参数
你可以通过 evaluate
方法的第二个参数传递参数给 JavaScript 代码:
void runJavaScriptWithArguments() async {
try {
final result = await jsScript.evaluate('a + b', {'a': 2, 'b': 3});
print('Result: $result'); // 输出: Result: 5
} catch (e) {
print('Error: $e');
}
}
6. 清理资源
当你不再需要使用 JsScript
实例时,可以调用 dispose
方法来释放资源:
void disposeJsScript() {
jsScript.dispose();
}
完整示例
以下是一个完整的示例,展示了如何在 Flutter 应用中使用 js_script
插件执行 JavaScript 代码:
import 'package:flutter/material.dart';
import 'package:js_script/js_script.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: JsScriptExample(),
);
}
}
class JsScriptExample extends StatefulWidget {
[@override](/user/override)
_JsScriptExampleState createState() => _JsScriptExampleState();
}
class _JsScriptExampleState extends State<JsScriptExample> {
final jsScript = JsScript();
String result = '';
void runJavaScript() async {
try {
final res = await jsScript.evaluate('1 + 1');
setState(() {
result = 'Result: $res';
});
} catch (e) {
setState(() {
result = 'Error: $e';
});
}
}
[@override](/user/override)
void dispose() {
jsScript.dispose();
super.dispose();
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('JsScript Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: runJavaScript,
child: Text('Run JavaScript'),
),
SizedBox(height: 20),
Text(result),
],
),
),
);
}
}