使用Node.js+React+EUI快速搭建网页应用

0. 起因

老板要搞个Log分析工具,数据存储选用的是Elasticsearch,起初想法是做个Kibana的插件,后来觉得依靠Kibana太庞大,而且后期想要把代码直接部署在GitHub page上,因此打算做成个独立的工具。最终选用了Node.js+React,主要原因是相中了一个React UI库EUI(Elastic Stack推出的一个开源UI库,风格与Kibana一样),毕竟,不是谁都能写出漂亮的UI,强如Linux之父Linus都表示“如果我被困在一个与世隔绝的岛上,逃离这座岛的唯一办法是写出漂亮的UI,那我估计就老死在岛上了”。
虽然最终由于内网权限问题没部署上GitHub page,但基本流程都跑通了。既然代码都写了,顺路写个总结吧。

1. 工程搭建

首先,我们需要安装Node.js,到Node.js官网随便下一个安装包安装,或者下载压缩包解压缩后手动设置环境变量使用。我比较喜欢直接使用压缩包,因为这样可以随意在多个版本间切换而且不用额外的工具辅助。例如在Ubuntu下下载压缩包解压缩并通过命令export PATH=$NODEJS_ROOT/bin:$PATH即完成了安装。安装完成后可以通过以下命令查看是否安装成功:

node --version
npm --version

安装完成后,按照以下结构建立一个目录:

my-app/
  package.json
  public/
    index.html
  src/
    index.js

其中my-app可以改成任意你喜欢的名字,剩余的部分名字必须与例子给出的一致,这是工程可以构建的前提。

然后,打开package.json,在其中填入以下内容并保存:

{
   
  "name": "eui-demo",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
   
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.5.0",
    "@testing-library/user-event": "^7.2.1",
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "react-scripts": "3.4.3"
  },
  "scripts": {
   
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
   
    "extends": "react-app"
  },
  "browserslist": {
   
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

上面的内容中,dependenciesscripts这两个对象必须有,其他的可选择性添加,即最小要求如下:

{
   
  "dependencies": {
   
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "react-scripts": "3.4.3"
  },
  "scripts": {
   
    "start": "react-scripts start",
  }
}

package.json文件准备好后执行以下命令:

npm install
npm start

执行完上面的命令,整个工程已经构建完毕,在浏览器中输入http://localhost:3000/即可访问你刚构建起来的应用,虽然目前这个应用什么也没做也没有显示任何内容。

当然,其实还有另一个更加简单的方法来构建应用,Node.js安装完成后只需要在终端输入一条命令即可 ,同样,my-app可以换成任意名字:

npx create-react-app my-app/

等待命令执行完毕即可。

2. Hello World?

如果工程是我们自己手动一步一步搭建起来的,通过浏览器访问http://localhost:3000/是什么都不会显示的。下一步,我们就需要让它显示点什么。编程嘛,就从Hello World开始吧。

首先,我们打开my-app/public/index.html,在里面输入一下信息并保存:

<html>
    <head></head>
    <body>
        <div id='content'>

        </div>
    </body>
</html>

上面的超文本标记代码很简单,如果用浏览器打开的话还是什么也看不到。它只是为后续的React UI代码提供了一个挂载点 —— id为content的一个div,在我们的小例子中,对HTML的编辑就算完了,身下的就全部交给JS代码了。

接着,我们打开my-app/src/index.js,输入一下代码:

import React from 'react';
import ReactDOM from 'react-dom';

function HelloWorld(props) {
   
	return (<div><p>Hello World!</p></div>)
}

ReactDOM.render(
  <HelloWorld />,
  document.getElementById('content')
);

编辑完my-app/src/index.js并保存之后,我们在my-app目录中执行npm start,就可以在浏览器中看到如图1结果:
图1 Hello World

图1 Hello World

在上面的代码中,我们做了三件事:

  1. 第一第二行代码分别从react以及react-dom这两个模块中导入了React以及ReactDOM这两个类。值得注意的是,虽然我们没有直接看到使用导入的React,但是这个导入语句是必须的,否则编译就会报错!
  2. 接下来,定义了一个名为HelloWorld的函数,这个函数在React中称为函数组件*(Function Components),它与类组件(Class Components)一起组成了React 渲染UI的核心。这个函数只有一个参数props,这个props实际上是一个字典,可以通过它传递任意参数给函数组件;函数返回一个描述如何显示UI的React元素,虽然看着像超文本标记语言(HTML),但是它却不是。它的名字叫做JSX(JavaScript eXtension),它是JavaScript语法的扩展。
  3. 第三步,就是将我们定义的函数组件通过ReactDOM.render()函数渲染出来。ReactDOM.render()需要一个挂载节点,在我们的例子中的挂载节点是前面提到的id为content的一个div,通过ReactDOM.render()渲染的界面都托管在React DOM中,由React DOM负责管理以及更新。

3. 实践

有了Hello World的铺垫,我们现在可以正式搭建一个简单点的应用了。我们选用的UI框架是Elastic UI,单然如果你有自己喜欢的其他框架也是可以的。

假设我们要搭建一个Markdown编辑器。我们确定它的结构如图2,我们需要用EUI实现我们的目标:
图2 Markdown 编辑器结构

图2 Markdown 编辑器结构
3.1. 搭架子

我们在EUI中找到一个名叫Page的布局空间,其布局如图3,正好符合我们的期望:
图3 Page空间布局样式

图3 Page空间布局样式

同样,我们分别找到导航组件(tree-view)、标签组件(tabs)以及Markdown编辑框组件(markdown-editor),将它们搭积木一样组合起来,并做些调整就能得到如图4所示的界面:
图4 Markdwon editor界面预览

图4 Markdwon editor界面预览

为了方便起见,我们将Page组件、导航栏组件、标签栏组件、编辑器组件代码放到独立JS文件中,分别命名为page.js, file-nav.js, tabs.js, markdown-editor.js,具体结构如下:

my-app/
  package.json
  public/
    index.html
  src/
    file-nav.js
    index.js
    markdown-editor.js
    page.js
    tabs.js

他们的代码分别如下所示:

// file-nav.js
import React from 'react';

import {
    EuiIcon, EuiTreeView, EuiToken } from '@elastic/eui';

export default () => {
   
  const showAlert = () => {
   
    alert('You squashed a bug!');
  };

  const items = [
    {
   
      label: 'src',
      id: 'src',
      icon: <EuiIcon type="folderClosed" />,
      iconWhenExpanded: <EuiIcon type="folderOpen" />,
      isExpanded: true,
      children: [
        {
   
          label: 'index.md',
          id: 'item_a',
          icon: <EuiIcon type="document" />,
        },
        {
   
          label: 'level2 folder',
          id: 'item_b',
          icon: <EuiIcon type="folderOpen" />,
          iconWhenExpanded: <EuiIcon type="folderOpen" />,
          children: [
            {
   
              label: 'monosodium_glutammate.md',
              id: 'item_cloud',
              icon: <EuiIcon type="document" />,
            },
            {
   
              label: "cobalt.md"
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值