65.9K
CodeProject 正在变化。 阅读更多。
Home

如何使用 React 构建销售仪表板

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2019年4月26日

CPOL
viewsIcon

5160

当涉及到企业级图表和图形组件,可以帮助你创建一个很棒的仪表板时,Wijmo 已经涵盖了你的需求。

创建仪表板时需要考虑很多事情。你如何将大量信息可视化,以帮助你的经理和主管做出重要决策?

作为一名 React 开发者,你可能会发现构建仪表板是你更具挑战性的职责之一。NPM 充满了图表和图形库,可以帮助你在截止日期前交付仪表板。但是,通过试错找到你需要的东西会非常耗时。

幸运的是,有更好的方法。当涉及到企业级图表和图形组件,可以帮助你创建一个很棒的仪表板时,Wijmo 已经涵盖了你的需求。

创建企业销售仪表板

让我们从定义开始。当我们说 仪表板 时,我们到底是什么意思?类似这样

这个就是你的经理在让你快点为他们做一个仪表板时脑子里想的。

现在,如果你正在阅读这篇文章,你可能是一名开发者而不是平面设计师。问题是:作为开发者,我们自己能做出多接近这个漂亮的仪表板示例?

使用 Wijmo,事实证明我们可以做到很接近。非常接近。

让我们来看看我们将要使用的工具和小部件。

工具

这些是我们用来构建仪表板的工具

Bootstrap

在一个拥有 Flexbox 和 CSS Grid 的世界里,Reddit 上的编程专家和自封的专家会告诉你,你不再需要像 Bootstrap 这样的 CSS 框架。他们说得技术上是正确的。

但是 Bootstrap 使得设置一个响应式的基于网格的应用程序变得非常容易,并且包含了一些额外的便利功能,可以节省我们的时间。既然我们是带有截止日期的开发者,我们将使用 Bootstrap。

当你制作自己的精彩仪表板时,可以随意使用 BootstrapBulmaTachyons,或者任何让你开心的东西。

本文将假设你熟悉 Bootstrap 的基础知识,但如果你以前从未用过,也没关系。当你看到像 col-sm-4, mt-1card 这样的 CSS 类名时,请记住它们是 Bootstrap CSS 的一部分。

React

如果你正在阅读这篇文章,你可能已经熟悉 React。但万一你不熟悉,它是一个由 Facebook 创建的非常棒的 JavaScript UI 构建库。

自 2013 年发布以来,它风靡全球。大大小小的公司都在广泛使用它。

它甚至已经通过 React Native 扩展到了 Web 之外。使用 React Native,你可以使用 React 和 JavaScript 创建出色的、快速的移动应用程序。

本文的其余部分将假定你已经熟悉基本的 React 概念,包括纯函数式组件。如果你还不是 React 高手,没关系!但在我们继续的过程中,如果你遇到任何你不确定的与 React 相关的代码片段,你可能需要查阅 React 文档。

Wijmo

Wijmo 是由 GrapeCity 创建的一套非常棒的企业级 JavaScript UI 控件。

它是创建炫酷仪表板、报告工具和业务应用程序的一站式服务,让你的经理、同事和最终用户惊叹于你的效率和快速的成果。

更好的是,Wijmo 提供了 React、Angular 和 Vue 的内置包装器。由于我们将使用 React 构建仪表板,这对我们来说是极好的消息。许多图表库要求我们使用 DOM refs 并花费数小时来正确地使图表工作。使用 Wijmo,一旦我们导入了想要的组件,就可以立即开始使用它们。

明星阵容

我们将使用几个特定的 Wijmo 组件来构建我们的仪表板。由于它们将是重头戏,让我们在深入研究创建它们所需的代码之前先快速了解一下它们。

FlexGrid

如果你有表格数据要显示,但又不想将其放入一个沉闷、丑陋的 HTML 表格中,Wijmo 的 FlexGrid 可以提供帮助。FlexGrid 配备了自动列生成、列排序和重新排序、编辑以及剪贴板支持。

FlexChart

FlexChart 是一款多才多艺的魔术师,可以显示多种类型的图表:柱状图、条形图、散点图、折线图、面积图和样条图——以及这些类型的几种组合!

我们将使用 FlexChart 在我们的仪表板中添加一个外观精美的条形图。

FlexPie

当你需要显示多个数据类别的大小比例时,你会找谁?FlexPie,就是它。

你可以将 FlexPie 用于任何地方,就像使用普通饼图一样,但 FlexPie 有一些不错的额外功能,使其在众多饼图中脱颖而出。

RadialGauge

当经理查看销售仪表板时,他们希望能够一目了然地知道本周的销售情况是好、尚可还是糟糕。RadialGauge 提供了这种能力,而且外观也很棒!

代码

为了保持简单,我们将使用 StackBlitz 来托管和运行我们的仪表板。所有必需的代码都可以通过点击此处查看。在生产应用程序中,你会希望将所有组件提取到单独的文件中。我在 index.js 中定义了所有内容,以便你可以快速了解一切,而无需来回跳转。

我们将逐一讲解代码的所有重要部分,但会跳过讨论与我们的应用程序不直接相关的样板代码。由于我们是带有截止日期的开发者,本文不会探讨 Wijmo 组件的每种可能的配置。如果我们尝试这样做,每个组件都需要自己的文章!

相反,在讲解完每个组件的代码后,我会告诉你可以在哪里更深入地探索该组件。现在,让我们开始吧!

index.js 顶部的所有导入之后,你会看到两个纯函数式组件

const ChartPanel = ({title, children}) => {
  return (
	<div className="col-lg-4 col-md-6 col-sm-12 mt-1">
  	  <div className="card dashboardPanel">
    	    <div className="card-body">
      	<h5 className="card-title">{title}</h5>
        	{children}
    	    </div>
  	  </div>
	</div>
  );
}

const DataPanel = ({title, children}) => {
  return (
	<div className="col-sm-12">
  	  <div className="card dashboardRow">
    	    <div className="card-body">
      	<h5 className="card-title">{title}</h5>
      	{children}
    	    </div>
  	  </div>
	</div>
  )
}

这些只是包装器,将我们大部分与 Bootstrap 相关的样板代码放在一个地方。当你准备自定义仪表板以满足你的需求并添加其他面板时,这些将非常有用,因为正如你即将看到的,使用这些包装器类可以非常轻松地创建你自己的仪表板面板,其中包含 Wijmo 控件!

接下来,我们创建一个显示我们公司今天销售额的 RadialGauge 面板

const Gauge = ({data}) => {
  return (
	<ChartPanel title="Today's Sales ($)">
  	  <div className="gauge">
    	    <RadialGauge
      	  min={ 0 } max={ 500000 }
      	  isReadOnly={ true }
      	  thickness={0.15}
      	  value={ data }
          />
  	  </div>
	</ChartPanel>
  );
}

我们的仪表组件很简单:它接收上面定义的 ChartPanel,并将其包装在一个 Wijmo RadialGauge 周围。我们传递了几个 props 来根据我们的需求进行自定义;我们设置了对我们的仪表板有意义的最小和最大值,使仪表仅可读,并设置了其厚度。

你会注意到我们的 Gauge 组件接受一个名为 data 的参数,并将其传递给 RadialGauge 的 value prop。这个值应该始终设置为一个数字,表示仪表当前设置的值。这个数字应始终在仪表 min 和 max 属性之间。

我们只使用了 RadialGauge 的少数选项。要更深入地了解它的功能,请查看 Wijmo Gauge 101 页面。

接下来,我们将添加一个条形图,该图将销售额按国家/地区细分

const SalesChart = ({salesData}) => {
  return (
	<ChartPanel title="Sales By Country">
  	  <FlexChart itemsSource={salesData}
              	   bindingX="country"
              	   style={{ height: "290px" }}>
    	    <FlexChartSeries name="Sales" binding="sales" />
  	  </FlexChart>
	</ChartPanel>
  );
}

就像我们对仪表组件所做的那样,我们将所有内容包装在我们的自定义 ChartPanel 中。在其中,我们添加了一个 Wijmo FlexChart。你会注意到我们传递了几个 props:itemsSourcebindingXstyle

style 很简单:它是一个包含 CSS 属性的对象,会传递给 Wijmo 图表。在这种情况下,我们只是设置了图表的高度,以确保它能整齐地放入我们的图表面板中。

itemsSource,顾名思义,包含将用于构建图表的数据项列表。该 prop 应传递一个 JavaScript 数组,其中包含至少一个用于 x 轴标签的字符串属性和一个包含 y 轴值的数字属性。FlexChart 将使用这些值来绘制图表条——或点、或线,取决于你选择的图表类型。在我们仪表板的情况下,我们图表的 itemsSource 如下所示

 const salesByCountry = [
 { country: "Canada", sales: 27250 },
 { country: "USA", sales: 107340},
 { country: "Germany", sales: 45360 },
 { country: "UK", sales: 66250}
]

接下来,我们看到 bindingX 设置为“country”。这只是告诉 Wijmo,当它遍历我们提供的 itemsSource 并构建图表时,它应该使用每个对象的 country 属性作为该数据点的 x 轴标签。

在 FlexChart 中,你会注意到一个 FlexChartSeries 元素。它接收两个 props:namebindingname 告诉 Wijmo 在图表图例中如何标记此数据系列,而 binding 告诉 Wijmo 使用每个数据项的哪个属性来呈现此数据系列。

尽管我们的仪表板图表只使用了一个数据系列,但 FlexChart 可以轻松地在单个图表上呈现多个数据系列。要更深入地了解 FlexChart 能为你做什么,请查看 FlexChart 101

const SalesPie = ({salesData}) => {
  return (
	<ChartPanel title="Sales by Salesperson">
    	  <FlexPie itemsSource={salesData}
                 binding="sales"
                 bindingName="name"
                 innerRadius={0.70}
                 style={{ height: "290px" }}/>
	</ChartPanel>
  );
}

接下来是 FlexPie。由于 FlexPie 是 FlexChart 的近亲,它接受非常相似的 props 集合。有一个重要的区别:FlexPie 只能显示单个数据系列,因为饼图上的多个系列没有太多意义!

因此,我们不是单独添加系列,而是直接将数据绑定属性提供给 FlexPie。让我们看看我们使用的所有 props

itemsSource 的工作方式与 FlexChart 中的相同。你应该传递一个 JavaScript 对象数组,其中包含一个用于标记图表图例中的数据点的字符串属性,以及一个用于渲染数据点的饼图楔形的数字属性。我们的 FlexPie 使用的数据如下所示

export const salesByPerson = [
 { name: "Bill", sales: 5500},
 { name: "Ted", sales: 7250},
 { name: "Angela", sales: 8500},
 { name: "Jill", sales: 10750}
]

接下来,bindingName 告诉我们应该使用每个数据对象的哪个属性来标记图表中的数据点。在我们的例子中,我们使用的是 name 属性。

binding 告诉 Wijmo 每个数据对象的哪个属性包含它应该用于计算该数据点的饼图楔形大小的数字值。

innerRadius 是一个有趣的属性:如果将其设置为 0 到 1 之间的值,它将掏空饼图的中心,并将你的饼图变成甜甜圈图!这并不是说普通的饼图有什么不好。它们很棒!将我们的图表变成甜甜圈图只是让它具有一种时髦的 21 世纪风格。

style 的工作方式与 FlexChart 相同。我们只是添加它以确保我们的甜甜圈图能整齐地放入其仪表板框中。要深入了解 FlexPie 能为你做什么,请查看 FlexPie 101

最后,让我们来看看显示最近交易列表的表格。我们使用的是 Wijmo FlexGrid,而不是一个普通的 HTML 表格

const TransactionList = ({transactions}) => {
  return (
	<DataPanel title="Recent Transactions">
	  <FlexGrid style={{width: "100%"}}
          	      itemsSource={transactions}>
    	  <FlexGridColumn header="Client Name" 
                        binding="client" width="2*" />
    	  <FlexGridColumn header="Description" 
                        binding="description" width="3*" />
    	  <FlexGridColumn header="Total ($)" 
                        binding="value" width="1*" />
    	  <FlexGridColumn header="Quantity" 
                        binding="itemCount" width="1*" />
  	  </FlexGrid>
	</DataPanel>
  );
}

哇!这里比我们之前的组件复杂得多。让我们一步一步地分解,看看发生了什么。

首先,我们将网格包装在 DataPanel 中,这是我们自定义的 Bootstrap 风格的容器组件之一。

接下来,我们创建 FlexGrid。注意我们传递了两个 props:styleitemsSource。我们之前都见过它们,它们在这里起着相同的目的。需要注意的一点是,传递给 itemsSource 的数据形状与我们到目前为止看到的数据形状略有不同

const recentSales = [
 { client: "Dunder Mifflin", 
   description: "Assorted paper-making supplies", 
   value: 4700, itemCount: 10},
 { client: "Utopia Planitia Shipyards", 
   description: "Dilithium, duranium, assorted shipbuilding supplies",
   value: 21750, itemCount: 250}
];

正如我们所见,我们有一个对象数组,其中包含字符串和数字属性的组合。每个对象属性都可以绑定到图表列。如果你不手动指定任何列,FlexGrid 会智能地为你生成一组列和列标题。

由于我们想要最大程度地控制数据的外观,你会注意到我们在 FlexGrid 中添加了多个 FlexGridColumns。我们向每个 FlexGridColumn 传递了三个 props:headerbindingwidth

header 告诉 Wijmo 使用什么标题文本来标记此列。

binding 告诉 Wijmo 它应该将每个数据对象的哪个属性绑定到此列。我特意设置了,以便我们的列标题与我们数据对象中的属性名称不完全匹配:例如,我们的 Quantity 列绑定到 itemCount 数据属性。

我选择这样做是因为从 API 或后端系统接收包含标签不清晰的数据非常普遍。多亏了 Wijmo 提供了添加自定义列绑定的能力,你不需要在将数据交给 Wijmo 之前进行大量的数据预处理。只需告诉 Wijmo 期望什么,它就会完成所有繁重的工作。

最后,我们向每列传递一个 width prop。我们传递的宽度值可能看起来有点奇怪:它们包含像 2\* 和 3\* 这样的值。星号大小调整是为 FlexGrid 定义动态大小的一种强大方法。Wijmo 的文档 对这一点进行了很好的解释,以及如何使用它来确保你的数据网格以你想要的方式渲染。

要全面了解 FlexGrid 的功能,请参阅 FlexGrid 101

让我们最后看一下我们最终的仪表板应用程序组件

class App extends Component {
 constructor() {
   super();
   this.state = {
     recentSales: recentSales,
     salesByCountry: salesByCountry,
     salesByPerson: salesByPerson
   };
 }

 calculateSales () {
   let totalSales = 0;
   this.state.recentSales.forEach(sale => totalSales += sale.value);
   return totalSales;
 }

 render() {
   return (
     <>
      <NavBar title="Sales Dashboard" />
      <div className="container">	         
        <div className="row">
         <Gauge data={ this.calculateSales() } />
         <SalesChart salesData={this.state.salesByCountry} />
         <SalesPie salesData={this.state.salesByPerson} />
        </div>
        <div className="row">
         <TransactionList transactions={this.state.recentSales} />
        </div>
      </div>
      </>
   );
 }
}

由于我们将自定义代码包装在自己的组件中,因此我们的 App 组件是 100% 标准的 React。我们导入了我们的虚拟数据并使用它来设置我们的初始应用程序状态,添加了一个方法来动态计算仪表板的销售数据,然后渲染我们所有的自定义组件。简单明了!

结果

在经历了所有这些代码之后,是时候看看最终结果了!你可以在 StackBlitz 上实时看到它:https://stackblitz.com/edit/react-wijmo-salesdash-udsdv7。最终结果是一个看起来像这样的仪表板

不错!我们是独自工作的开发者,我们已经快速地组装了一个看起来相当不错的仪表板!而且由于 Bootstrap 的响应式 CSS,它在移动设备上看起来也很棒。

而这仅仅是开始。为什么不从我们在这里构建的代码开始,并将其作为你自己的炫酷 Wijmo 仪表板的基础呢?

结论

正如我们所见,你可以使用 Wijmo 组件快速轻松地创建生产就绪的仪表板。想想看,如果你自己创建带有内置排序和过滤功能的网格视图,需要花费多少时间。

Wijmo 的组件通过提供工具让你能够立即创建外观精美的企业仪表板,从而帮助你进行创新——无需花费数小时试图拼凑开源工具包或自己构建解决方案。

考虑到这一点,请记住我们创建的仪表板只是一个起点。一篇文章远不足以涵盖 Wijmo 的整个工具集;我们只是触及了 Wijmo 能为你做什么的表面。要更好地了解 Wijmo 能帮助你实现什么,首先要阅读所有 Wijmo 的控件,然后在 Wijmo 组件浏览器 中实时查看控件。

© . All rights reserved.