Flutter web - 6 Dart 与 JavaScript 互操作

介绍

flutter web 中, 使用 dart:js_interopJavaScript 应用程序和库以及浏览器API进行通信,Web 开发人员可以在 Dart 代码中使用外部 JS库,而无需在 Dart 中重写任何内容。

使用

Dart 官方推荐使用 package:web 来替代 dart:htmldart:indexed_dbdart:svgdart:web_audiodart:web_gl 库。使用dart:js_interopdart:js_interop_unsafe替代package:jsdart:jsdart:js_util

package:web

使用 package:web 需升级 dart sdk3.4.0

安装 package:web,在 pubspec.yaml 中加入 web: ^1.0.0,然后执行 flutter pub get

dependencies:
  web: ^1.0.0

引入 package:web

import 'package:web/web.dart' as web;

void main() {
  print('innerHeight: ${web.window.innerHeight}');
}

在这里插入图片描述

dart:js_interop

dart:js_interop 是一个内置的库,无需进行安装。

操作函数

假设项目中引入了一个 js 文件,内容如下:

function doSomething() {
  console.log('invoke doSomething function')
}

dart 中,要怎么调用这个 doSomething 函数呢?

import 'dart:js_interop';

('doSomething')
external void doSomething();

void main() {
  doSomething();
}

在这里插入图片描述

js-interop 文档 中表示,处于顶级互操作成员(声明在全局作用域下的)必须使用@JS()注释声明。

@JS('doSomething') 表示要与 javascript 全局作用域下的 doSomething 互操作,我们知道这个 doSomething 是一个函数,所以它的类型定义为 external void doSomething();external 表示外部的,是一个固定的关键字,然后接上函数的返回值类型,再接上函数名。即可完成一个函数的定义。后面就可以直接使用 doSometing() 来调用该函数。

接下来,来定义一个具有参数和返回值类型的函数:

function doSomething2(num) {
  return num;
}
import 'dart:js_interop';

('doSomething2')
external JSNumber doSomething2(JSNumber num);

void main() {
  print(doSomething2(100.toJS)); // 100
}

这个例子中,可以看到 100 后面加了 .toJS,因为 js类型dart类型 基本是不互通的,所以需要通过 toJS 来转换成 js类型

操作普通对象

假设引入的 script 文件为:

var obj = {
  name: 'Tom',
  age: 12,
}

那么 dart 中表示为:

第一种定义方式:

('obj')
external JSObject obj;

当我们调用 obj.age 时,会提示 The setter 'age' isn't defined for the type 'JSObject'. Try importing the library that defines 'age', correcting the name to the name of an existing setter, or defining a setter or field named 'age'. 需要为 obj 定义 age 字段。

为了解决报错,使用第二种定义方式:

import 'dart:js_interop';
import 'package:web/web.dart' as web;

extension type objType._(JSObject _) implements JSObject {
  external JSString name;
  external JSNumber age;
}

('obj')
external objType obj;

web.console.log(obj);
web.console.log(obj.age);

这里给 obj 定义了类型 objType

在这里插入图片描述

操作数组

var arr = [1, 2, 3];
extension type Array._(JSArray<JSAny> _) implements JSArray<JSAny> {
  external JSAny operator [](int index);
  external void operator []=(int index, JSAny value);
  external JSNumber get length;
  external JSAny push(JSAny value);
}

('arr')
external Array arr;

web.console.log(arr);        // [1, 2, 3]
web.console.log(arr[0]);     // 1
arr[0] = 100.toJS;           
web.console.log(arr[0]);     // 100
web.console.log(arr.length); // 3
arr.push(123.toJS);   
web.console.log(arr);        // [100, 2, 3, 123]

操作类

class Person {
  constructor(name, age) {
    this._name = name;
    this._age = age;
  }

  get name() {
    return this._name;
  }

  set name(name) {
    this._name = name;
  }

  get age() {
    return this._age;
  }

  set age(age) {
    this._age = age;
  }

  static eat() {
    console.log("eat");
  }
}

globalThis.Person = Person; // 注意这一行
extension type Person._(JSObject _) implements JSObject {
  external Person(JSString name, JSNumber age);

  external JSNumber age;
  external JSString name;

  external static void eat();
}

Person p = Person('Tom'.toJS, 12.toJS);
web.console.log(p);      // Person {_name: 'Tom', _age: 12 }
web.console.log(p.name); // Tom
p.name = 'Tom111'.toJS;
web.console.log(p.name); // Tom111
Person.eat();            // eat
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值