Внедрение JavaScript в Flutter WebView — Полное руководство

Внедрение JavaScript в Flutter WebView — Полное руководство

FlutterPulse

Эта статья переведена специально для канала FlutterPulse. В этом канале вы найдёте много интересных вещей, связанных с Flutter. Не забывайте подписываться! 🚀

Веб-представление Flutter — webview_flutter мощное для встраивания веб-контента, но иногда вам нужно больше, чем просто загрузка страницы.

Что если вы хотите:

  • Захватить значения формы ввода (например, имя пользователя или электронную почту)?
  • Динамически изменять элементы DOM?
  • Добавить пользовательские слушатели кликов?
  • Общаться между веб-страницей и Flutter?

Именно здесь появляется внедрение JavaScript.

В этом руководстве мы научимся, как внедрить JavaScript в WebView, захватить значения и отправить их обратно в Flutter.

Добавление webview_flutter

Чтобы начать, добавьте пакет в свой pubspec.yaml:

dependencies:
flutter:
sdk: flutter
webview_flutter: ^4.8.0

(Всегда проверяйте pub.dev на наличие последней версии.)

webview_flutter | Пакет Flutter

Плагин Flutter, который предоставляет виджет WebView, поддерживаемый системой webview.

pub.dev

️ Настройка WebView

Сначала давайте настроим WebView с включенным неограниченным JavaScript:

final WebViewController controller =
WebViewController.fromPlatformCreationParams(params)
..setJavaScriptMode(JavaScriptMode.unrestricted)
..addJavaScriptChannel(
'FormChannel',
onMessageReceived: (JavaScriptMessage message) {
debugPrint("Перехвачено из WebView: ${message.message}");
},
)
..loadRequest(Uri.parse("https://example.com/login"));

Здесь мы создали канал JavaScript (FormChannel), который действует как "мост" между JavaScript и Flutter.

‍ Внедрение JavaScript

Теперь давайте внедрим некоторый JavaScript, когда страница завершит загрузку:

Future<void> _injectCustomHook() async {
await _controller.runJavaScript('''
(function() {
const loginButton = document.querySelector('button[type="submit"]');
if (loginButton) {
loginButton.addEventListener('click', function() {
const input = document.getElementById('username')?.value || '';
FormChannel.postMessage(input);
});
}
})();
''');
}

Что делает этот код

  • Находит кнопку входа внутри WebView.
  • Слушает событие клика.
  • Читает поле ввода с идентификатором username.
  • Отправляет его обратно в Flutter, используя FormChannel.

Получение данных в Flutter

Данные поступают обратно во Flutter через канал JavaScript:

..addJavaScriptChannel(
'FormChannel',
onMessageReceived: (JavaScriptMessage message) {
debugPrint("Пользователь ввел: ${message.message}");
// Используйте значение в вашем приложении
},
)

Если пользователь вводит hello@example.com в веб-форме, Flutter выводит следующее в консоли:

Пользователь ввел: hello@example.com

🚀 Почему инъекция JavaScript мощна

С помощью инъекции JS вы можете:

  • Перехватить значения ввода перед их отправкой.
  • Автоматически заполнить формы.
  • Скрыть или переоформить нежелательные элементы.
  • Добавить дополнительную функциональность к существующим веб-страницам.

Пример: Скрыть баннер внутри WebView

await _controller.runJavaScript('''
document.querySelector('.ads-banner')?.style.display = 'none';
''');

🧩 Окончательный справочный код

Вот полный справочный код, объединяющий настройку WebView, инъекцию JavaScript и захват данных:

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

class WebViewExample extends StatefulWidget {
const WebViewExample({super.key});

@override
State<WebViewExample> createState() => _WebViewExampleState();
}

class _WebViewExampleState extends State<WebViewExample> {
late final WebViewController _controller;

@override
void initState() {
super.initState();

final params = const PlatformWebViewControllerCreationParams();
final controller = WebViewController.fromPlatformCreationParams(params)
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setNavigationDelegate(
NavigationDelegate(
onPageFinished: (url) {
_injectCustomHook();
},
),
)
..addJavaScriptChannel(
'FormChannel',
onMessageReceived: (JavaScriptMessage message) {
debugPrint("Перехвачено из WebView: ${message.message}");
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Пользователь ввел: ${message.message}")),
);
},
)
..loadRequest(Uri.parse("https://example.com/login"));

_controller = controller;
}

Future<void> _injectCustomHook() async {
await _controller.runJavaScript('''
(function() {
const loginButton = document.querySelector('button[type="submit"]');
if (loginButton) {
loginButton.addEventListener('click', function() {
const input = document.getElementById('username')?.value || '';
FormChannel.postMessage(input);
});
}
})();
''');
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("Инъекция JS в WebView")),
body: WebViewWidget(controller: _controller),
);
}
}

🔄 Альтернативы

Хотя webview_flutter поддерживает базовую инъекцию JS, другие пакеты предлагают больше:

  1. flutter_inappwebview
flutter_inappwebview | Пакет Flutter

Плагин Flutter, который позволяет добавить встроенный веб-просмотр, использовать безголовый веб-просмотр и открывать встроенный браузер…

pub.dev

Расширенная инъекция JS, перехват сетевых запросов, управление cookie и лучший выбор, если вам нужен глубокий контроль над страницей.

2. flutter_web_auth_2

flutter_web_auth_2 | Пакет Flutter

Плагин Flutter для аутентификации пользователя с помощью веб-сервиса.

pub.dev

Открывает системный браузер вместо инъекции JS и отлично подходит для потоков OAuth.

Лучшие практики

  • Всегда очищайте и проверяйте данные, полученные из внедренного JavaScript.
  • Тестируйте на нескольких платформах (Android и iOS ведут себя немного по-разному).
  • Избегайте чрезмерного использования внедрения JS — используйте его только тогда, когда родные API Flutter или API бэкенда не могут достичь того же.

Заключение

Внедрение JavaScript — это как дать вашему Flutter WebView суперспособности. В следующий раз, когда вы встраиваете веб-страницу в Flutter, не просто отображайте ее — внедряйте свою логику и делайте ее умнее!

Report Page