flutter-web中使用js工具类
文章目录
- 为什么要调用js
- 1. flutter-web
- 1. 引入js web/index.html
- 2. 创建工具js web/CryptoEnc.js
- 3. 创建对应的lib/js/js_interop.dart
- 4. 由于引入的js是针对web平台的,所以引入需要做引入处理
- 5. 使用
- 2. Android
- 1. 引入依赖
- 2. index.html
- 3. dart
- 引用
为什么要调用js
JavaScript拥有庞大且成熟的工具生态系统
1. flutter-web
1. 引入js web/index.html
<!-- Add the required JS libraries -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.2.0/crypto-js.min.js" integrity="sha512-a+SUDuwNzXDvz4XrIcXHuCf089/iJAoN4lmrXJg18XnduKK6YlDHNRalv4yd1N40OKI80tFidF+rqTFKGPoWFQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.2.0/md5.min.js" integrity="sha512-ENWhXy+lET8kWcArT6ijA6HpVEALRmvzYBayGL6oFWl96exmq8Fjgxe2K6TAblHLP75Sa/a1YjHpIZRt+9hGOQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<!-- Register the js file where the logic is written -->
<script src="CryptoEnc.js" type="application/javascript"></script>
2. 创建工具js web/CryptoEnc.js
function CryptoEnc() {}
CryptoEnc.prototype.encrypt = function(toEncObj){
var toEnc = toEncObj.value;
var encrypted = CryptoJS.MD5(toEnc);
return encrypted;
}
CryptoEnc.prototype.testFunc = function(toEncObj2){
var toEnc = toEncObj2.value;
return "========bbbbtestFunc"+toEnc;
}
3. 创建对应的lib/js/js_interop.dart
// #1
()
library js_interop;
// The above two lines are required
import 'package:js/js.dart';
// #2
()
class CryptoEnc {
external CryptoEnc();
external String encrypt(ToEncrypt toEncrypt);
external String testFunc(ToEncrypt2 toEncrypt2);
}
// #3
()
class ToEncrypt {
external String get value;
external factory ToEncrypt({String value});
}
()
class ToEncrypt2 {
external String get value;
external factory ToEncrypt2({String value});
}
4. 由于引入的js是针对web平台的,所以引入需要做引入处理
///encrypt.dart
class ToEncrypt {
final String value;
ToEncrypt({
required this.value,
});
}
class ToEncrypt2 {
final String value;
ToEncrypt2({
required this.value,
});
}
class CryptoEnc {
CryptoEnc();
String encrypt(ToEncrypt toEncrypt) {
// We are not implementing any encryption for mobile for now.
// This is just for demonstration.
throw UnimplementedError();
}
String testFunc(ToEncrypt2 toEncrypt) {
// We are not implementing any encryption for mobile for now.
// This is just for demonstration.
throw UnimplementedError();
}
}
///export_encrypt.dart
export 'encrypt.dart' if (dart.library.js) 'js_interop.dart';
5. 使用
var encVal = CryptoEnc().encrypt(
ToEncrypt(
value: "aaaaaa",
),
);
var encVal2 = CryptoEnc().testFunc(ToEncrypt2(
value: "cccc",
));
print(encVal);
print("testFunc=$encVal2");
2. Android
1. 引入依赖
webview_flutter: ^4.4.2
2. index.html
<!DOCTYPE html>
<html>
<head>
<title>Test js dart</title>
</head>
<body>
<script>
function inputClick (url) {
console.log('inputClick=>'+url);
}
function playUrl(url) {
console.log('playUrl=>'+url);
}
function startPlay() {
console.log('startPlay');
}
function postMsg() {
console.log('postMsg');
//向dart发送消息
Print.postMessage('postMsg');
}
</script>
</body>
</html>
3. dart
import 'package:flutter/material.dart';
import 'package:tvboxstudy/log_extensions.dart';
import 'package:webview_flutter/webview_flutter.dart';
class LocalHtmlWebView extends StatefulWidget {
const LocalHtmlWebView({super.key});
LocalHtmlWebViewState createState() => LocalHtmlWebViewState();
}
class LocalHtmlWebViewState extends State<LocalHtmlWebView> {
late String localHtmlContents;
late WebViewController controller;
ValueNotifier<bool> isShowLoading = ValueNotifier(true);
void initState() {
super.initState();
initController();
loadLocalHtml();
_registerJavascriptChannel();
}
void runJS(int type) {
if (type == 1) {
controller.runJavaScript(
'inputClick();',
);
} else if (type == 2) {
controller.runJavaScript(
'startPlay();',
);
}else if (type == 3) {
controller.runJavaScript(
'postMsg();',
);
} else if (type == 4) {
controller.runJavaScript(
"playUrl('https://media.w3.org/2010/05/sintel/trailer.mp4');",
);
}
}
void _registerJavascriptChannel() {
controller.addJavaScriptChannel(
'Print',
onMessageReceived: (JavaScriptMessage message) {
//收到消息做相应的处理
print("onMessageReceived=>${message.message}");
},
);
}
void initController() {
controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setBackgroundColor(Colors.transparent)
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setNavigationDelegate(
NavigationDelegate(
onProgress: (int progress) {
"progress=$progress".log();
if (progress == 100) {
isShowLoading.value = false;
}
},
onPageStarted: (String url) {},
onPageFinished: (String url) {
controller
.runJavaScriptReturningResult('document.body.scrollHeight')
.then((value) {
"scrollHeight=>$value".log();
});
},
onWebResourceError: (WebResourceError error) {},
onNavigationRequest: (NavigationRequest request) {
if (request.url.startsWith('https://www.youtube.com/')) {
return NavigationDecision.prevent;
}
return NavigationDecision.navigate;
},
),
);
}
void loadLocalHtml() async {
controller.loadFlutterAsset('assets/www/player/index2.html');
}
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Row(
children: [
TextButton(onPressed: (){
runJS(1);
}, child: Text("inputClick")),
TextButton(onPressed: (){
runJS(2);
}, child: Text("startPlay")),
TextButton(onPressed: (){
runJS(3);
}, child: Text("postMsg")),
TextButton(onPressed: (){
runJS(4);
}, child: Text("playUrl")),
],
),
Expanded(
child: Stack(
children: [
WebViewWidget(
controller: controller,
),
ValueListenableBuilder(
valueListenable: isShowLoading,
builder: (BuildContext context, bool value, Widget? child) {
return isShowLoading.value
? const Center(
child: CircularProgressIndicator(
color: Colors.white,
))
: const SizedBox.shrink();
},
)
],
),
),
],
),
);
}
}
引用
Utilizing JS Library for Flutter Web