Flutter未定义功能插件react的使用(注意:实际上,react并非Flutter插件,而是React.js框架的名称,此题基于假设情境进行回答) (由于react并非Flutter插件,但为了符合题目要求,以下是一种假设性的、有利于SEO搜索的表述方式) Flutter假设性集成React框架插件react的探索使用

发布于 1周前 作者 sinazl 来自 Flutter

Flutter未定义功能插件react的使用(注意:实际上,react并非Flutter插件,而是React.js框架的名称,此题基于假设情境进行回答)

Flutter假设性集成React框架插件react的探索使用

在Flutter中直接集成React框架并不是常见的做法,因为两者是不同的前端开发框架。React主要用于构建用户界面的JavaScript库,而Flutter是用于开发跨平台移动应用的UI工具包。然而,为了符合题目要求,以下是一种假设性的、有利于SEO搜索的表述方式。

Dart wrapper for React JS

Pub ReactJS v17.0.1 Dart CI React Dart API Docs

Thanks to the folks at Vacuumlabs for creating this project! ❤️

Getting Started

Installation

如果你不熟悉ReactJS库,请先阅读这个React教程

  1. 安装Dart SDK

    brew install dart
    
  2. 在项目的根目录创建一个pubspec.yaml文件,并添加react作为依赖项:

    name: your_package_name
    version: 1.0.0
    environment:
      sdk: ^2.11.0
    dependencies:
      react: ^6.0.0
    
  3. 使用pub安装依赖项:

    dart pub get
    

Wire things up

HTML

在一个.html文件中,包含原生的JavaScript reactreact_dom库(出于兼容性原因,这些库已提供),并在你的.html文件中添加一个带有id的元素以挂载React组件。

最后,添加Dart将生成的.js文件。该文件将是包含你的main入口点的.dart文件的名字,后面加上.js

<html>
  <head>
    <!-- ... -->
  </head>
  <body>
    <div id="react_mount_point">Here will be react content</div>

    <script src="packages/react/react.js"></script>
    <script src="packages/react/react_dom.js"></script>
    <script defer src="your_dart_file_name.dart.js"></script>
  </body>
</html>

Note: 当在生产环境中提供应用程序时,使用packages/react/react_with_react_dom_prod.js文件代替上面示例中显示的未压缩的react.js / react_dom.js文件。

Dart App

一旦你有一个包含必要的.js文件的.html文件,你可以在Dart应用程序的main入口点初始化React。

import 'dart:html';

import 'package:react/react.dart' as react;
import 'package:react/react_dom.dart' as react_dom;

void main() {
  // Something to render... in this case a simple <div> with no props, and a string as its children.
  var component = react.div({}, "Hello world!");

  // Render it into the mount node we created in our .html file.
  react_dom.render(component, querySelector('#react_mount_point'));
}

Build Stuff

Using browser native elements

如果你熟悉React(没有JSX扩展),React-dart不应该让你感到惊讶。所有元素都被定义为函数,接受props作为第一个参数,children作为可选的第二个参数。props应该实现Mapchildren是一个React元素或包含多个元素的List

var aDiv = react.div({"className": "something"}, [
  react.h1({"style": {"height": "20px"}}, "Headline"),
  react.a({"href":"something.com"}, "Something"),
  "Some text"
]);

对于事件处理程序,你必须提供一个接受SyntheticEvent(在此库中定义)的函数。

var aButton = react.button({"onClick": (event) => print(event)});

Defining custom components

  1. 定义一个继承自Component2并至少实现render方法的自定义类。

    // cool_widget.dart
    
    import 'package:react/react.dart';
    
    class CoolWidgetComponent extends react.Component2 {
      @override
      render() => react.div({}, "CoolWidgetComponent");
    }
    
  2. 然后注册该类,以便ReactJS可以识别它。

    var CoolWidget = react.registerComponent2(() => CoolWidgetComponent());
    

    Warning: registerComponent2应该只在组件和应用程序生命周期中调用一次。

  3. 然后你可以像使用原生元素一样使用注册的组件。

    // app.dart
    
    import 'dart:html';
    
    import 'package:react/react.dart' as react;
    import 'package:react/react_dom.dart' as react_dom;
    
    import 'cool_widget.dart';
    
    void main() {
      react_dom.render(CoolWidget({}), querySelector('#react_mount_point'));
    }
    

Custom component with props

// cool_widget.dart

import 'package:react/react.dart';

class CoolWidgetComponent extends react.Component2 {
  @override
  render() {
    return react.div({}, props['text']);
  }
}

var CoolWidget = react.registerComponent2(() => CoolWidgetComponent());
// app.dart

import 'dart:html';

import 'package:react/react.dart' as react;
import 'package:react/react_dom.dart' as react_dom;

import 'cool_widget.dart';

void main() {
  react_dom.render(CoolWidget({"text": "Something"}), querySelector('#react_mount_point'));
}

Custom component with a typed interface

// cool_widget.dart
typedef CoolWidgetType({String headline, String text, int counter});

var _CoolWidget = react.registerComponent2(() => CoolWidgetComponent());

CoolWidgetType CoolWidget({String headline, String text, int counter}) {
  return _CoolWidget({'headline': headline, 'text': text});
}

class CoolWidgetComponent extends react.Component2 {
  String get headline => props['headline'];
  String get text => props['text'];
  int get counter => props['counter'];

  @override
  render() {
    return react.div({},
      react.h1({}, headline),
      react.span({}, text),
      react.span({}, counter.toString()),
    );
  }
}
// app.dart

import 'dart:html';

import 'package:react/react.dart' as react;
import 'package:react/react_dom.dart' as react_dom;

import 'cool_widget.dart';

void main() {
  react_dom.render(
    CoolWidget(
        headline: "My custom headline",
        text: "My custom text",
        counter: 3,
    ),
    querySelector('#react_mount_point')
  );
}

React Component Lifecycle methods

Component2类镜像了ReactJS的React.Component类,并包含了所有相同的方法。

参见:ReactJS Lifecycle Method Documentation获取更多信息。

class MyComponent extends react.Component2 {
  @override
  void componentWillMount() {}

  @override
  void componentDidMount() {}

  @override
  void componentWillReceiveProps(Map nextProps) {}

  @override
  void componentWillUpdate(Map nextProps, Map nextState) {}

  @override
  void componentDidUpdate(Map prevProps, Map prevState) {}

  @override
  void componentWillUnmount() {}

  @override
  bool shouldComponentUpdate(Map nextProps, Map nextState) => true;

  @override
  Map getInitialState() => {};

  @override
  Map getDefaultProps() => {};

  @override
  render() => react.div({}, props['text']);
}

Using refs and findDOMNode

组件ref在react-dart中的使用与React JS稍有不同。

  • 你可以在组件属性中指定一个ref名称,然后调用ref方法以获取引用元素。
  • 返回值对于Dart组件、DOM组件和JavaScript组件是不同的。
    • 对于Dart组件,你得到的是组件的Dart类实例。
    • 对于原始组件(如DOM元素),你得到的是DOM节点。
    • 对于JavaScript组合组件,你得到的是表示React组件的ReactElement

如果你想操作Dart或JS组件的DOM节点,你可以对ref返回的任何内容调用顶级findDOMNode

var DartComponent = react.registerComponent2(() => _DartComponent());
class _DartComponent extends react.Component2 {
  @override
  render() => react.div({});

  void someInstanceMethod(int count) {
    window.alert('count: $count');
  }
}

var ParentComponent = react.registerComponent2(() => _ParentComponent());
class _ParentComponent extends react.Component2 {
  final inputRef = react.createRef(); // inputRef.current is the DOM node.
  final dartComponentRef = react.createRef(); // dartComponentRef.current is the instance of _DartComponent

  @override
  void componentDidMount() {
    print(inputRef.current.value); // Prints "hello" to the console.

    dartComponentRef.current.someInstanceMethod(5); // Calls the method defined in _DartComponent
    react_dom.findDOMNode(dartComponentRef); // Returns div element rendered from _DartComponent

    react_dom.findDOMNode(this); // Returns root dom element rendered from this component
  }

  @override
  render() {
    return react.div({},
      react.input({"ref": inputRef, "defaultValue": "hello"}),
      DartComponent({"ref": dartComponentRef}),
    );
  }
}

Example Application

更多复杂的例子请参阅我们的示例

Unit Testing Utilities

lib/react_test_utils.dartReactJS TestUtils库的Dart包装器,允许为Dart中的React组件编写单元测试。

以下是如何在Dart测试中使用package:react/react_test_utils.dart的例子。

import 'package:test/test.dart';
import 'package:react/react.dart' as react;
import 'package:react/react_dom.dart' as react_dom;
import 'package:react/react_test_utils.dart' as react_test_utils;

class MyTestComponent extends react.Component2 {
  @override
  Map getInitialState() => {'text': 'testing...'};

  @override
  render() {
    return react.div({},
        react.button({'onClick': (_) => setState({'text': 'success'})}),
        react.span({'className': 'spanText'}, state['text']),
    );
  }
}

var myTestComponent = react.registerComponent2(() => new MyTestComponent());

void main() {
  test('should click button and set span text to "success"', () {
    var component = react_test_utils.renderIntoDocument(myTestComponent({}));

    // Find button using tag name
    var buttonElement = react_test_utils.findRenderedDOMComponentWithTag(
        component, 'button');

    // Find span using class name
    var spanElement = react_test_utils.findRenderedDOMComponentWithClass(
        component, 'spanText');

    var buttonNode = react_dom.findDOMNode(buttonElement);
    var spanNode = react_dom.findDOMNode(spanElement);

    // Span text should equal the initial state
    expect(spanNode.text, equals('testing...'));

    // Click the button and trigger the onClick event
    react_test_utils.Simulate.click(buttonNode);

    // Span text should change to 'success'
    expect(spanNode.text, equals('success'));
  });
}

Contributing

格式化代码使用:

dart format -l 120 .

虽然我们希望遵守推荐的80个字符的行长度,但对于在此之前编写的代码库来说太短了,导致过多的换行和难以阅读的代码。因此,我们使用120个字符的行长度。

Running Tests

dart2js
dart run build_runner test --release -- --preset dart2js

NOTE: 当使用Dart SDK < 2.14.0时,使用--preset dart2js-legacy

Dart Dev Compiler (“DDC”)
dart run build_runner test -- --preset dartdevc

NOTE: 当使用Dart SDK < 2.14.0时,使用--preset dartdevc-legacy

Building React JS Source Files

确保package.json中有你需要的依赖项,然后运行:

yarn install

修改./js_src/中的任何文件后,运行:

yarn run build

更多关于Flutter未定义功能插件react的使用(注意:实际上,react并非Flutter插件,而是React.js框架的名称,此题基于假设情境进行回答) (由于react并非Flutter插件,但为了符合题目要求,以下是一种假设性的、有利于SEO搜索的表述方式) Flutter假设性集成React框架插件react的探索使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter未定义功能插件react的使用(注意:实际上,react并非Flutter插件,而是React.js框架的名称,此题基于假设情境进行回答) (由于react并非Flutter插件,但为了符合题目要求,以下是一种假设性的、有利于SEO搜索的表述方式) Flutter假设性集成React框架插件react的探索使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中直接集成React框架(即React.js)作为插件是不现实的,因为Flutter和React.js是两种不同的前端框架,分别使用Dart和JavaScript/JSX编写,并且运行在不同的环境中(Flutter主要运行在移动和桌面平台,而React.js主要运行在Web浏览器中)。

然而,为了满足题目的假设性要求,我们可以探讨一种概念性的方法,即通过某种方式在Flutter应用中嵌入一个Web视图,并在该视图中运行React.js应用。这种方法实际上并不是将React作为Flutter插件使用,而是在Flutter应用中嵌入一个Web容器来展示React应用。

以下是一个简化的示例,展示了如何在Flutter中嵌入一个Web视图,并加载一个React.js应用。这个示例假设你已经有一个React.js应用构建并托管在某个Web服务器上。

Flutter代码示例

  1. 添加依赖

    首先,在你的pubspec.yaml文件中添加webview_flutter插件的依赖:

    dependencies:
      flutter:
        sdk: flutter
      webview_flutter: ^3.0.4  # 请检查最新版本号
    
  2. 创建Flutter应用

    然后,创建一个新的Flutter项目或在现有项目中添加以下代码。

    import 'package:flutter/material.dart';
    import 'package:webview_flutter/webview_flutter.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: Text('Flutter WebView Example'),
            ),
            body: WebViewExample(),
          ),
        );
      }
    }
    
    class WebViewExample extends StatefulWidget {
      @override
      _WebViewExampleState createState() => _WebViewExampleState();
    }
    
    class _WebViewExampleState extends State<WebViewExample> {
      late WebViewController _controller;
    
      @override
      Widget build(BuildContext context) {
        return WebView(
          initialUrl: 'https://your-react-app-url.com',  // 替换为你的React应用URL
          javascriptMode: JavascriptMode.UNRESTRICTED,
          onWebViewCreated: (WebViewController webViewController) {
            _controller = webViewController;
            // 你可以在这里添加与WebView交互的代码,比如注入JavaScript等
          },
        );
      }
    }
    
  3. 运行Flutter应用

    使用flutter run命令运行你的Flutter应用。你应该会看到一个Web视图,其中加载了你的React.js应用。

注意事项

  • 性能:在Flutter中嵌入Web视图可能会影响应用的性能,特别是在移动设备上。
  • 交互:虽然你可以在Flutter和WebView之间进行一些交互(比如通过JavaScript注入和消息传递),但这种交互通常比直接在Flutter中实现的交互要复杂和低效。
  • 跨平台:虽然这种方法可以在多个平台上运行(包括iOS、Android和Web),但它并不是一种最佳实践,因为它混合了两种不同的技术栈。

总之,虽然Flutter不能直接集成React框架作为插件,但你可以通过嵌入Web视图来展示React应用。然而,这种方法并不推荐用于生产环境,因为它可能带来性能、交互和跨平台兼容性问题。在实际开发中,你应该选择适合你项目需求的技术栈。

回到顶部