本博客是一系列构建小部件中的第一篇,旨在帮助您熟悉如何构建自己的可插入小部件 Mendix。博客将涵盖越来越复杂的概念,并涵盖一系列用例,包括熟悉 Typescript 和可插拔小部件 API、在浏览器中运行机器学习模型以及构建基本的 WebAssembly 游戏。
从哪里开始
如果你还没有,你应该查看一下这个工作示例来创建你的第一个可插入小部件:
可插入小部件使用 React Javascript 框架,我们将在本系列中介绍一些 React 概念,但这绝不是对 React 的全面介绍。因此,如果您需要介绍或复习,我强烈推荐以下课程(您甚至可能会发现此小部件的灵感来源): React 教程:学习 React JS – 免费 11 小时课程
本博客的目的
在此博客中,我们将介绍:
- 可插入小部件项目结构
- 测试设置和开发
- React 概念介绍
- 利用外部库
我们正在建设什么
我们将构建一个计数器,它可以通过单击按钮来增加或减少,并且单击时颜色会随机改变。

项目的最终状态可以在这里找到: GitHub – joe-robertson-mx/colourCount
新会员入门指南
首先,我们使用 Mendix 小部件生成器哟@mendix/widget 颜色计数。这为我们提供了 HelloWorld 实现。

文件夹结构:
我们的小部件文件夹具有以下结构:
- dist — 我们构建和捆绑的代码将输出的位置
- node-modules——我们的节点依赖项
- src-我们的 src 代码文件夹
- components — 每个组件文件夹的 jsx 文件
- ui — 用于设置小部件样式的 css
- package.xml — 描述小部件结构
- colourCount.editorConfig.ts — Studio Pro 和 Studio 中设计模式预览的配置
- colourCount.editorPreview.jsx — 在 Studio Pro 和 Studio 中提供预览的组件
- colourCount.tsx — 小部件的入口点
- colourcount.xml — 描述小部件和 Mendix
- package.json — 描述我们的 npm 项目和小部件依赖项
- prettier.config.js — 允许我们修改代码的更漂亮的规则
测试和开发设置
为了方便测试,我们创建一个新的空白 Mendix 我们针对小部件的版本中的项目,位于 ./colourCount/tests/testProject


开始运行
完成后,让我们运行构建脚本并测试我们的小部件。
从终端导航到小部件根目录,然后输入
npm 运行构建
这将在我们的 dist/ 文件夹和测试应用程序的 widgets 文件夹中创建一个 widget 包。
要查看该小部件的运行情况,我们只需在 Studio Pro 中打开测试应用程序并按 F4 同步文件目录即可。然后,我们可以像添加其他小部件一样将小部件添加到页面中。
为了配置我们的小部件并验证参数是否从建模器传递到前端的小部件,我们可以添加一些文本来传递。

当我们运行应用程序时,我们可以看到

我们的小部件的部署和测试过程是可行的,但速度有点慢。为了加速这个过程,我们可以通过运行
npm运行开始
这将监视我们的代码的变化,为了看到它们反映出来,我们只需要清除缓存并强制重新加载。
这可以在 Chrome 中通过打开 Chrome 开发者工具 (Ctrl + Shift +i),右键单击刷新按钮并选择“清空缓存并硬重新加载”来完成。

编写代码
编码时间到了!
开始之前先做一些小改动
让我们从我们的反应代码开始,首先让我们将我们的组件重命名为更合理的名称:Count。
首先,我们重命名 HelloWorld.jsx 中的组件。
import { createElement } from "react";
import { Count } from "./components/Count";
import "./ui/ColourCount.css";
export function ColourCount({ sampleText }) {
return <Count sampleText={sampleText ? sampleText : "World"} />
}
最佳做法是重命名文件以匹配 ColourCount 中的组件。
我们需要将 src/ui 处的 CSS 文件重命名为 ColourCount.css – 以便正确导入。我们还必须更新子组件,为此,我们首先将 HelloWorldSample.jsx 重命名为 Count.jsx,并将其中的组件名称更新为 Count。
export function Count({ sampleText }: HelloWorldSampleProps) {
return <div className="widget-hello-world">
Hello {sampleText}
</div>;
}
为了加快开发过程,我们将更改 editorPreview 文件,使其不依赖于其余代码,方法是像这样更新它
import { ReactElement, createElement } from "react";
export function preview() {
return <div />;
}
export function getPreviewCss() {
return require("./ui/ColourCount.css");
}
在开始更新组件之前,让我们将子组件重命名为更合理的名称:“Count”。为此,我们需要更新 ColourCount 父组件以引用 components/Count 文件中包含的 Count 组件。
我们的小部件构建可以分为 3 个部分:
- 更新 Mendix 小部件接口接受一个数字作为计数器的起始值
- 创建逻辑来更改此数字
- 将随机颜色变化添加到数字中
更新 Mendix 小部件界面
之间的接口 Mendix 模型和您的小部件在 ColourCounter.xml 标记中定义。我们需要更新我们的模型以接受数字值,方法是更改“示例文本和 财产 到以下内容:
<property key="initialValue" type="integer" required="true" defaultValue="5">
<caption>Initial Value</caption>
<description>The initial value of the counter</description></property>
如果我们打开 Mendix 模型,按 F4 并更新小部件。打开小部件时,您将看到我们的新界面。

然而,这尚未连接到我们的组件。
为了做到这一点,我们需要更换 示例文本 - 初始值 在 ColourCount 文件中:
import { createElement } from "react";
import { Count } from "./components/Count";
import "./ui/ColourCount.css";
export function ColourCount({ initialValue }) {
return <Count initialValue={initialValue} />;
}
在 Count 文件中
export function Count({ initialValue }) {
return <div>{initialValue}</div>;
}
如果我们重新运行我们的应用程序,我们可以看到我们呈现的初始值:

属性(或 props)从 Mendix 应用程序到 ColourCount 组件,它在函数中被解构并传递给 Count 组件。
创建逻辑来更改此数字
在 React 中,不应直接更改 Props。相反,我们将更改的属性存储在组件状态中。
为了利用功能组件中的状态,我们使用 useState 钩子。
Hooks 是在 React 16.8 版本中引入的。它允许你无需编写类即可使用状态和其他 React 功能。Hooks 是一些函数,用于从函数组件中“钩住” React 状态和生命周期功能。它无法在类内部使用。 阅读有关 React 中的 Hooks 的更多信息。
首先我们需要添加 使用状态 进口。
import { createElement, useState } from "react";
然后我们将下面的代码添加到Count组件。
export function Count({ initialValue }) {
const [count, setCount] = useState (initialValue)
return <div>{count}</div>;
}
当我们打电话时 使用状态 它返回一个状态变量数组和一个设置状态变量的函数。它立即被解构为 数 陈述和 设置计数 功能。
它接受 初始值 作为参数,在创建时设置计数变量的值。
现在我们可以使用以下方法改变状态 设置计数。设置状态时,您可以简单地传入一个值,或者像本例一样,您可以使用之前的状态作为函数中的参数。
了解了这一点,我们可以添加一个函数来增加状态值。
export function Count({ initialValue }) {
const [count, setCount] = useState (initialValue)
const increment = () => {
setCount(prevState => prevState + 1);
};
return <div>{initialValue}</div>;
}
我们可以对减量函数做同样的事情。
现在我们需要更新 JSX 来呈现我们应用程序想要的 HTML:
export function Count({ initialValue }) {
const [count, setCount] = useState (initialValue)
const increment = () => {
setCount(prevState => prevState + 1);
};
const decrement = () => {
setCount(prevState => prevState - 1);
};
return (
<div>
<p>{count}</p>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
</div>
);
}
当我们运行应用程序时,我们现在可以增加和减少 州,显示在小部件中:

将随机颜色变化添加到数字中
现在,我们希望在计数发生变化时生成随机颜色。这将是一段耗时的代码,幸运的是,我们可以使用存储在 npm 注册表中的预先编写的软件包: 随机颜色
该包提供了一个函数,当调用时,它会以字符串形式返回随机颜色。利用这个包很容易:首先,我们通过运行来安装该包 npm install randomcolor 在我们的小部件文件夹中。
然后我们开始修改 Count 文件中的代码。首先我们导入函数
import randomColor from 'randomcolor';
然后我们需要启动一些状态来保存我们的颜色属性
const [colour, setColour] = useState('')
我们还需要将颜色反映在小部件的样式中,为此,我们可以使用 HTML 标签的 style 属性。style 属性接受具有您希望应用的样式属性的 JS 对象。
阅读有关使用 React 设置 Dom 元素样式的更多信息。
在这里,我们可以使用内置的 Mendix 类:
import { createElement, useState } from 'react'
import randomColor from 'randomcolor'
export function Count({ initialValue }) {
const [count, setCount] = useState(initialValue)
const [colour, setColour] = useState('')
const increment = () => {
setCount((prevState) => prevState + 1)
}
const decrement = () => {
setCount((prevState) => prevState - 1)
}
return (
<div>
<p style={{ color: colour }}>{count}</p>
<button className="mx-button btn-primary" onClick={increment}>
+
</button>
<button className="mx-button" onClick={decrement}>
-
</button>
</div>
)
现在,我们需要在 count 变量发生变化时触发颜色变化。为此,我们可以使用 React 中提供的关键实用程序之一: 使用效果.
使用效果 是一个钩子,它在组件的每次渲染时调用一个函数(副作用)。通过添加以下内容,我们可以在渲染时将颜色设置为随机值:
import { createElement, useState } from 'react'
import randomColor from 'randomcolor'
export function Count({ initialValue }) {
const [count, setCount] = useState(initialValue)
const [colour, setColour] = useState('')
useEffect(() => {
setColour(randomColor())
}, [])
const increment = () => {
setCount((prevState) => prevState + 1)
}
const decrement = () => {
setCount((prevState) => prevState - 1)
}
return (
<div>
<p style={{ color: colour }}>{count}</p>
<button className="mx-button btn-primary" onClick={increment}>
+
</button>
<button className="mx-button" onClick={decrement}>
-
</button>
</div>
)
当我们在浏览器中运行它时,我们得到...DISCO COUNT!

这很酷,但绝对不是我们想要的。那么为什么会发生这种情况呢?
好吧,如果我们在 useEffect 中放置一个 console.log('Render'),我们可以看到组件正在重复重新渲染,这是因为组件在状态或 props 发生任何变化时都会重新渲染。因此,当我们在 useEffect 中设置颜色状态时 它会导致重新渲染和无限循环.
幸运的是,这个问题很容易解决。 useEffect 钩子接受第二个参数,即要监视的状态和/或属性的数组。这意味着该函数仅在监视的状态/属性之一发生变化时运行。我们只希望在计数发生变化时颜色发生变化,因此我们将 useEffect 更新为:
useEffect(() => {
setColour(randomColor())
}, [count])
注意:要仅运行 useEffect 一次,请在组件加载时添加一个空数组作为第二个参数
现在,当我们更新我们的小部件时...VOILA!

概括
在这篇博客中,我们介绍了如何使用可插入小部件 Mendix,如何设置您的开发环境以及一些核心 React 概念,包括 state、props 和 useEffect。
该小部件的最终代码可以在这里找到: GitHub – joe-robertson-mx/colourCount
接下来是什么?
接下来我们将开始使用 Typescript,直接与 Mendix 实体和属性,并了解如何触发我们的 Mendix 来自我们的小部件的模型。
让我们知道您对这篇文章的看法。您希望看到哪些小部件?请在此处的评论中提出有关未来小部件的任何建议。
资源中心
要了解有关可插入式小部件的更多信息,以下资源可能会有所帮助: 入门 – React, 构建可插入的 Web 小部件,