О загрузке html во Flutter Web

Flutter

   Недавно столкнулся с требованием загрузить html в веб-проекте Flutter. На мобильном мы можем использоватьwebview_pluginПлагин загружен, но он недействителен в Интернете. Итак, во Flutter Web, как загрузить html? Flutter предоставляет нам элемент управления специально для Интернета:HtmlElementView. (В качестве отступления здесь написано, что в документе комментариев HtmlElementView написано, что построение html — дорогостоящая операция. Если есть эквивалентная реализация Flutter, которую можно заменить, постарайтесь не делать этого.)

Основные правила использования HtmlElementView

  Будьте осторожны при использовании этого элемента управления,Перед использованием обязательна регистрация! ! !
допустимыйinitState()При регистрации, конечно, вы также можетеrunApp()Когда пора регистрироваться глобально (лично не рекомендую):

import 'dart:ui' as ui;
ui.platformViewRegistry.registerViewFactory(
        'hello-world-html',
        (int viewId) => HtmlElement();

  ui.platformViewRegistryОн сообщит о статической ошибке, не беспокойтесь об этом, это никак не повлияет на ваш код. пожалуйста, объясниregisterViewFactory()В метод передаются два параметра: первое личное понимание — дать имя id фрагменту html, который нужно вставить, а второй параметр — это соответствующий элемент, который фактически используется для загрузки html. здесьHtmlElement()Это базовый класс, который следует передавать при написании.IFrameElement,HtmlHtmlElement,MediaElement,BodyElementи так далее для элементов, которые вам действительно нужны.
использоватьHtmlElementView, вам нужно только передать идентификатор, соответствующий зарегистрированному элементу:

HtmlElementView(
    viewType: 'hello-world-html',
    )

Загрузить URL

   Можно использовать URL загрузкиIFrameElement(Пожалуйста, напишите весь адрес, не пропуститеhttps):

ui.platformViewRegistry.registerViewFactory(
        'hello-world-html',
        (int viewId) => IFrameElement()
          ..style.border = 'none'
          ..src = 'https://www.baidu.com');

Загрузить локальный html-файл

ui.platformViewRegistry.registerViewFactory(
        'hello-world-html',
        (int viewId) => IFrameElement()
          ..style.border = 'none'
          ..src = '/assets/test2.html');

загрузить html-строку

  • Загрузить более сложный смешанный HTML (короче)

   Если это HTML, смешанный с различными тегами, вы можете использоватьHtmlHtmlElement:

ui.platformViewRegistry.registerViewFactory(
        'hello-world-html',
        (int viewId) => HtmlHtmlElement()
          ..style.border = 'none'
          ..setInnerHtml(html));

   Обратите внимание на ямки здесь, потому что html, используемый в реальном проекте, содержит<img>,<a href>Ярлык и тому подобное нормальные, но если загрузить картинку, то гиперссылка не отображается указанным выше образом, потому что по умолчаниюHtmlHtmlElementЭти теги отключены (предположительно для производительности, в конце концов, как я сказал в начале, Flutter на самом деле не хочет, чтобы вы загружали html-теги напрямую), вам нужно вручную включить загрузку сложных тегов. Конкретный метод заключается в передачеvalidatorпараметр:

final NodeValidator _validator = NodeValidatorBuilder.common()
    ..allowElement('img', attributes: ['src'], uriPolicy: _AllowUriPolicy())
    ..allowElement('a', attributes: ['href'], uriPolicy: _AllowUriPolicy());
    
ui.platformViewRegistry.registerViewFactory(
        'hello-world-html',
        (int viewId) => HtmlHtmlElement()
          ..style.border = 'none'
          ..setInnerHtml(html,validator: _validator));
         
class _AllowUriPolicy implements UriPolicy {
  @override
  bool allowsUri(String uri) {
    return true;
  }
}
  • Загрузить более сложный смешанный HTML (длиннее)

   Если это длинный html, если вы используетеHtmlHtmlElementЗагрузившись, вы обнаружите, что страницу невозможно прокрутить. нужно пройтиScrollViewКомбинированный дисплей, но будьте осторожны,HtmlElementViewНеобходимо рассчитать высоту:

ui.platformViewRegistry.registerViewFactory(
        'hello-world-html',
        (int viewId) => HtmlElementView()
          ..style.border = 'none'
          ..innerHtml = content);

   Про расчет: можно пройтиscrollOffsetПолучить высоту, но будет проблема с этим получением высоты, высота точна при входе на страницу в первый раз, но если вы измените размер окна, высота станет неточной. Временным решением является принудительная повторная отправка страницы при прослушивании изменения размера окна (во Flutter Web изменение размера самого окна восстановит текущую страницу, включая виджеты и данные, но это похоже на повторную отправку). он другой, с какими-то кешированными данными?scrollOffsetприобретенныйHtmlElementViewвысота увеличивается без проводов). Если у вас есть лучшее решение, пожалуйста, оставьте сообщение и дайте мне знать.
мощныйIFrameElementВы также можете загрузить смешанный HTML, используяsrcdocспособ загрузки, но IFrameElement, если иScrollViewСовмещать будет хлопотнее, высоту этой штуки рассчитать не так-то просто (надеюсь, здоровяк, умеющий считать, меня научит):

ui.platformViewRegistry.registerViewFactory(
        'hello-world-html',
        (int viewId) => IFrameElement()
          ..style.border = 'none'
          ..srcdoc = content);
  • Загрузите html одного тега

  Рекомендуется использовать легкийMediaElement,BodyElement,FormElement,MenuElementи т.п.