调用您的Ember应用程序中的React组件
#javascript #react #webpack #ember

在这篇文章中,我们将研究如何从ember.js应用程序调用React组件。在研究主题之前,让我们快速介绍这两个框架(或库),看看为什么我们要首先将React集成到Ember Codebase中。

余烬

Ember是雄心勃勃的网络开发人员的框架。这是一个富有成效的战斗测试JavaScript框架,用于构建现代网络应用程序。它包括您构建在任何设备上工作的丰富UI所需的一切。它已经存在了10多年,并且仍然受到许多公司的优先和使用。

反应

React当然并不需要介绍,因为它是JavaScript框架空间中无可争议的领导者。它是用于构建用户界面的JavaScript库。它是基于声明性和组成部分的。使用React,您可以构建封装的组件来管理自己的状态,然后构成它们以制造复杂的UI。

为什么?

可能有许多理由将REACT集成到ember.js应用程序中,从性能,可维护性,技术异质性,组织原因,开发人员可用性为业务优先级。我的Emberanos同胞在这些原因上不会完全同意我的看法。没关系。但是,我想分享我在最近进行的一些实验中分享我的知识,以帮助更大的人社区以及那些希望从Ember迁移到反应的人。

重要的是要记住,Ember并不是一个坏框架。在JavaScript框架方面,Ember仍然是我的初恋。 。您真的无法将Ember与React绝对术语进行比较。因为它是苹果和橙子。

设置monorepo

我们将为这篇文章设置一个monorepo。这使我们有一个明确的优势,即将React组件和Ember应用程序分别保留在单个存储库中。我们将使用pnpm workspaces进行手头的任务。

|-app
|--|-<Ember app>
|-some-react-lib
|--hello-world.jsx
|--package.json
|-README.md
|-pnpm-lock.yaml
|-pnpm-workspace.yaml

这是我使用命令行设置monorepo结构的方式。

mkdir ember-react-example
cd ember-react-example
touch README.md pnpm-workspace.yaml
mkdir app some-react-lib
cd app
degit ember-cli/ember-new-output#v4.10.0
cd ..
cd some-react-lib
touch hello-world.jsx package.json

在这里,我正在使用degit来引导我们的ember应用程序,因为ember-cli不允许您以app的名义创建一个新的ember应用。

我们的pnpm-workspace.yaml文件应该看起来像这样的东西,表明工作区包含两个软件包一个ember应用程序和其他react组件库。

packages:
  - app
  - some-react-lib

编译用灰烬的反应组件

现在,我们将看到如何使用ember-auto-import配置Ember Build Pipeline,以调整下面的WebPack构建器以编译JSX。在此之前,我们需要添加适当的依赖项,以编译reactreact-dom本身和其他babel插件(例如React)。

因此,从您的Ember App root文件夹中,运行以下命令以添加依赖项。

pnpm add -D react react-dom babel-loader @babel/preset-react

这是Ember应用程序内的修改后的ember-cli-build.js文件的样子。我们正在配置WebPack加载程序,以从Monorepo内的React软件包some-react-lib处理所有JSX。

'use strict';

const EmberApp = require('ember-cli/lib/broccoli/ember-app');

module.exports = function (defaults) {
  let app = new EmberApp(defaults, {
    autoImport: {
      webpack: {
        module: {
          rules: [
            {
              test: /some-react-lib\/.*\.jsx/,
              use: {
                loader: 'babel-loader',
                options: {
                  presets: [['@babel/preset-react', { runtime: 'automatic' }]],
                },
              },
            },
          ],
        },
      },
    }
  });

  return app.toTree();
};

通过修饰符渲染组件

修饰符是与Ember中DOM相互作用的基本原始性。例如,Ember带有内置修饰符{{on}}

<button {{on "click" @onClick}}>
  {{@text}}
</button>

所有修饰符都会直接应用于元素(如果您看到不在元素中的相似值,则可能是助手),并且在应用其效果时将通过元素传递。

从概念上讲,修饰符采用跟踪,派生状态并将其转变为某种副作用,以某种方式与它们应用于。

要创建我们的修饰符,我们将在Ember应用程序中使用ember-modifier插件。让我们首先安装我们的插件。

ember install ember-modifier

让我们创建一个基于类的修饰符来渲染我们的React组件。

ember g modifier react --class

这是新创建的修饰符的代码。基本上,修饰符正在尝试为React组件创建一个新的根元素,然后创建一个React组件的新实例,并将其在修饰符提供的元素中渲染。 @ember/destroyable中可用的registerDestructor功能将帮助您拆除修饰符时添加的功能。

import Modifier from 'ember-modifier';
import { createRoot } from 'react-dom/client';
import { createElement } from 'react';
import { registerDestructor } from '@ember/destroyable';

export default class ReactModifier extends Modifier {
  modify(element, [reactComponent], props) {
    if (!this.root) {
      this.root = createRoot(element);
      registerDestructor(this, () => this.root.unmount());
    }
    this.root.render(createElement(reactComponent, { ...props }));
  }
}

反应组件

我们的React组件是一个简单的组件,显示可以使用Ember组件的动作来切换消息的消息。
这是我们的React组件的代码。

export function HelloWorld({ message, onClick }) {
  return <div>
    <button onClick={onClick}>Toggle</button>
    <div>you said: {message}</div>
  </div>;
}

创建Ember包装组件

让我们创建我们的包装组件,为此我们需要一个带有类的微光组件

ember g component example -gc

ember component.js

Ember包装组件的代码很简单。首先,我们是从MonorePo中的共享库中导入React组件,并将其分配给称为theReactComponent的组件属性,我们将将主要参数使用给修饰符。然后,我们有一个跟踪的属性消息和一个动作切换,这两个都构成了React组件。

import { HelloWorld } from 'some-react-lib/hello-world.jsx';
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';

export default class extends Component {
  theReactComponent = HelloWorld;

  @tracked message = 'hello';

  @action toggle() { 
    if (this.message === 'hello') {
      this.message = 'goodbye';
    } else {
      this.message = 'hello';
    }
  }
}

Ember组件模板

这就是我们在DOM元素上使用react修饰符来渲染我们的React组件并通过道具传递数据。

<div {{react this.theReactComponent message=this.message onClick=this.toggle}} />

这就是Ember应用的样子。基本上,我们正在使用按钮切换一条消息。消息数据和消息处理程序功能都通过修饰符道具从Ember传递到React组件。

Image description

优点缺点

在Ember应用程序中使用了React组件后,让我们讨论使用上述方法将React React集成到Ember.js应用程序的利弊。

优点

  • 逐步迁移ember代码库
  • 具有Ember和React组件的单向波
  • 易于消耗组件,通过道具传递数据并与修饰语语法共享状态
  • 干净而简单的方法

缺点

  • 需要每个React组件的Ember包装组件
  • 如果更改React组件中的代码,则热模块重新加载将无法工作,因为它是NPM的单独依赖性
  • 框架在您的生产捆绑包中额外40 kb(反应运行时)

样品回购

该帖子的代码托管在github here中。非常感谢Edward Faulkner使之成为可能。使用embroider,还有一种绣花versionversion来构建和编译以路线代码拆分的组件。

请看一下GitHub存储库,让我知道您的反馈,在评论部分中查询。如果您觉得这里有更多的利弊,请告诉我们。