首页 > 解决方案 > flutter web : 如何找到 iframeElement 来替换它的 src

问题描述

我有一个颤振项目,我为其添加了网络支持。现在在我的页面中,我有 2 个按钮。我想在用户单击每个按钮时显示一个网页。所以为了创建自定义小部件:

  @override
  Widget build(BuildContext context) {
    print("url is ------> ${url}");
    isAddedElement();
    _iframeElement.height = double.maxFinite.toString();
    _iframeElement.width = double.maxFinite.toString();
    _iframeElement.src = url;
    _iframeElement.style.border = 'none';
    _iframeElement.id = 'iframe';

    ui.platformViewRegistry.registerViewFactory(
      'iframeElement',
      (int viewId) => _iframeElement,
    );
    _iframeWidget = HtmlElementView(
      // key: UniqueKey(),
      viewType: 'iframeElement',
    );
    return SizedBox(
      height: 600,
      width: 600,
      child: _iframeWidget,
    );
  }

isAddedElement我想检查的方法中iframeElement.id = 'iframe'是否存在?如果存在我想用新网页更改 src:

  bool isAddedElement() {
    IFrameElement frame = document.querySelector('iframe');
    if (frame != null) frame.src = url;
  }

document.querySelector('iframe')总是返回null?

标签: flutterflutter-web

解决方案


查询返回null,很可能是因为颤振HtmlElementView在 a 中添加了小部件,shadowDom而这些元素不能直接在document作用域中使用。

为了访问元素,您需要通过shadowroot通常放置在名为flutter-platform-view.

因此,以下方法可能有效。

通过访问flt-platform-view

尝试访问 iframe 元素,如下所示。

document.getElementsByTagName('flutter-platform-view')[0].shadowRoot.getElementById('iframe');

访问 IframeElement 实例

您已经有了IframeElement实例的引用,可以使用它检查您需要的内容,如下所示。

  bool isAddedElement() {
    //IFrameElement frame = document.querySelector('iframe');
    if (_iframeElement!= null && _iframeElement.src == null) _iframeElement.src = url;
  }

但是我不明白为什么在你的代码中你isAddedElement()甚至在设置 IframeElement 之前就调用了。

你可以在 github的这个问题中找到更多关于它为什么放在影子 dom 后面的细节。

这是使用第一种方法的完整工作演示。实时版本可作为codepen演示使用

import 'package:flutter/material.dart';
import 'dart:ui' as ui;
import 'dart:html';

final Color darkBlue = Color.fromARGB(255, 18, 32, 47);

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: IframeDemo(),
        ),
      ),
    );
  }
}

class IframeDemo extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return MyWidget();
  }
}

class MyWidget extends State<IframeDemo> {
  String _url;
  IFrameElement _iframeElement;

  @override
  initState() {
    super.initState();
    _url = 'https://en.wikipedia.org/wiki/Twitter';
    _iframeElement = IFrameElement()
      ..src = _url
      ..id = 'iframe'
      ..style.border = 'none';
    ui.platformViewRegistry.registerViewFactory(
      'iframeElement',
      (int viewId) => _iframeElement,
    );
  }

  void updateUrl(String page) {
    setState(() {      
      // building a new url
      _url = 'https://en.wikipedia.org/wiki/$page';
      
      // Setting the url to the src field of the iframe element.
      HtmlElement elem = document.getElementsByTagName('flt-platform-view')[0];
      IFrameElement ifrelem = elem.shadowRoot.getElementById('iframe');
      ifrelem..src = _url;
    });
  }

  @override
  Widget build(BuildContext context) {
    print('url is $_url');

    return Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            MaterialButton(
              color: Colors.blueAccent,
              child: Text('Show Twitter wiki'),
              onPressed: () {
                updateUrl('Twitter');
              },
            ),
            SizedBox(
              width: 50,
            ),
            MaterialButton(
              color: Colors.orangeAccent,
              child: Text('Show Facebook Wiki'),
              onPressed: () {
                updateUrl('Facebook');
              },
            ),
          ],
        ),
        SizedBox(
          height: 100,
        ),
        SizedBox(
          height: 600,
          width: 600,
          child: HtmlElementView(
            // key: UniqueKey(),
            viewType: 'iframeElement',
          ),
        ),
      ],
    );
  }
}


推荐阅读