插件介绍

web_embedding 是一个展示如何在网页应用中嵌入 Flutter 应用的示例集合,无需使用 iframe。该包提供了在不同 Web 框架中集成 Flutter Web 应用的解决方案,支持元素级嵌入和跨框架 JavaScript 互操作。

核心功能特点:

  • 元素级嵌入:将 Flutter 应用嵌入到网页的特定 DOM 元素中,实现精细的布局控制
  • 跨框架集成:支持在多种 Web 框架(如 Angular、React 等)中嵌入 Flutter 应用
  • 双向 JS 互操作:Flutter 和 JavaScript 之间的无缝通信,支持方法调用和事件监听
  • 自定义初始化:灵活的初始化配置,支持指定 hostElement 和加载选项
  • 多示例展示:包含基础嵌入示例和框架集成示例,覆盖不同使用场景
  • 响应式设计:支持与网页其他元素的响应式布局和交互

使用步骤

1. 包的引入

由于这是一个自定义修改版本,需要通过 Git 形式引入。在您的项目的 pubspec.yaml 文件中添加以下依赖配置:

dependencies:
  web_embedding:
    git:
      url: "https://atomgit.com/"
      path: "packages/web_embedding/web_embedding"

然后运行以下命令获取依赖:

flutter pub get

2. 基础嵌入配置

在您的鸿蒙应用中,首先需要在 HTML 中定义一个用于嵌入 Flutter 的 DOM 元素:

<!DOCTYPE html>
<html>
  <head>
    <!-- 其他元标签和样式 -->
    <script src="flutter.js" defer></script>
  </head>
  <body>
    <!-- 其他页面内容 -->
    <div id="flutter_target"></div>

    <script>
      window.addEventListener("load", function (ev) {
        // 嵌入 Flutter 到 div#flutter_target
        let target = document.querySelector("#flutter_target");
        _flutter.loader.loadEntrypoint({
          onEntrypointLoaded: async function (engineInitializer) {
            let appRunner = await engineInitializer.initializeEngine({
              hostElement: target,
            });
            await appRunner.runApp();
          },
        });
      });
    </script>
  </body>
</html>

3. Flutter 应用配置

在您的 Flutter 应用中,配置支持 JS 互操作的导出方法:

import 'package:flutter/material.dart';
import 'package:js/js.dart' as js;
import 'package:js/js_util.dart' as js_util;

void main() {
  runApp(const MyApp());
}

.JSExport()
class _MyAppState extends State<MyApp> {
  int _counter = 0;

  
  void initState() {
    super.initState();
    final export = js_util.createDartExport(this);
    js_util.setProperty(js_util.globalThis, '_appState', export);
  }

  .JSExport()
  void increment() {
    setState(() {
      _counter++;
    });
  }

  .JSExport()
  int get count => _counter;

  // 其他 Flutter 组件代码...
}

4. JavaScript 互操作

在 JavaScript 中与嵌入的 Flutter 应用进行交互:

// 当 Flutter 应用准备好时
window._stateSet = function () {
  // 获取 Flutter 应用状态对象
  let appState = window._appState;

  // 调用 Flutter 方法
  let incrementButton = document.querySelector("#increment");
  incrementButton.addEventListener("click", (event) => {
    appState.increment();
  });

  // 获取 Flutter 状态值
  console.log(appState.count);
};

API 调用

1. Flutter 加载 API

_flutter.loader.loadEntrypoint({
  onEntrypointLoaded: async function (engineInitializer) {
    // 初始化 Flutter 引擎
    let appRunner = await engineInitializer.initializeEngine({
      hostElement: targetElement, // 指定嵌入的 DOM 元素
      // 其他引擎配置选项
    });
    // 运行 Flutter 应用
    await appRunner.runApp();
  },
  // 其他加载选项
});

2. JS 互操作 API

Flutter 导出方法到 JS
.JSExport()
void myMethod(String parameter) {
  // Flutter 方法实现
}

.JSExport()
int get myProperty => _value;
JS 调用 Flutter 方法
// 调用导出的方法
appState.myMethod("参数");

// 获取导出的属性
let value = appState.myProperty;
Flutter 监听 JS 事件
.JSExport()
void addEventListener(void Function() handler) {
  // 注册事件监听器
}
// 添加事件监听
appState.addEventListener(() => {
  console.log("Flutter 事件触发");
});

3. Angular 集成 API

在 Angular 中嵌入 Flutter 应用:

import { Component, EventEmitter, Output } from '@angular/core';

@Component({
  selector: 'ng-flutter',
  template: '<div id="flutter-container"></div>',
})
export class NgFlutterComponent {
  @Output() appLoaded = new EventEmitter<any>();

  ngAfterViewInit() {
    window.addEventListener('flutter-initialized', (event: any) => {
      this.appLoaded.emit(event.detail);
    });

    // 加载 Flutter 应用
    // ...
  }
}

鸿蒙适配注意事项

1. WebView 配置

在鸿蒙应用中,需要使用 WebView 组件来承载嵌入的 Flutter Web 应用:

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

class FlutterEmbeddingScreen extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Flutter 嵌入示例')),
      body: WebView(
        initialUrl: 'assets/index.html',
        javascriptMode: JavascriptMode.unrestricted,
        onWebViewCreated: (controller) {
          // 配置 WebView 控制器
        },
      ),
    );
  }
}

2. 资源文件处理

确保在鸿蒙应用中正确处理 Flutter Web 应用的资源文件:

# pubspec.yaml
flutter:
  assets:
    - assets/index.html
    - assets/flutter.js
    - assets/flutter_service_worker.js
    # 其他资源文件

3. 权限配置

在鸿蒙应用中配置必要的网络和存储权限:

<!-- config.json -->
"module": {
  "reqPermissions": [
    {
      "name": "ohos.permission.INTERNET",
      "reason": "需要访问网络加载 Flutter 资源"
    }
  ]
}

4. 性能优化

  • 合理设置 WebView 的缓存策略
  • 优化 Flutter Web 应用的体积和加载速度
  • 避免频繁的 JS 互操作调用
  • 使用懒加载和代码分割优化初始加载时间

高级应用场景

1. 跨框架状态同步

实现 Flutter 和 Web 框架之间的状态同步:

// Flutter 端
exportState() {
  final state = {'counter': _counter, 'text': _text};
  broadcastAppEvent('state-updated', state);
}
// JS 端
window.addEventListener('state-updated', (event) => {
  let state = event.detail;
  // 更新 Web 框架状态
  updateAppState(state);
});

2. 自定义事件系统

建立 Flutter 和 JS 之间的自定义事件系统:

// Flutter 端
void broadcastEvent(String eventName, dynamic data) {
  js.context.callMethod('dispatchEvent', [
    js.JsObject(js.context['CustomEvent'], [
      eventName,
      js.JsObject.jsify({'detail': data}),
    ]),
  ]);
}
// JS 端
window.addEventListener('flutter-event', (event) => {
  let data = event.detail;
  // 处理事件数据
});

总结

web_embedding 提供了一种强大的方式来将 Flutter 应用嵌入到网页应用中,实现了元素级的集成和双向的 JavaScript 互操作。通过将其适配到鸿蒙系统,开发者可以在鸿蒙应用中使用 WebView 承载嵌入的 Flutter Web 应用,充分利用 Flutter 的 UI 能力和 Web 技术的灵活性。

该包的核心价值在于打破了 Flutter 和 Web 技术之间的壁垒,使得开发者可以在同一应用中结合两种技术的优势。通过遵循本指南,您可以轻松地将 web_embedding 集成到您的鸿蒙应用中,并实现复杂的跨技术栈交互。

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐