项目实训–生物信息深度学习平台 个人总结3

2021SC@SDUSC

项目静态文件修改

index.html

这个文件在public文件夹下,是项目运行的静态html文件,核心是一个

<body>
    ...
    <div id="root"></div>
</body>

其中,id为root的div元素是React渲染的根节点。
需要修改的主要是项目icon、标题title等需要根据项目具体情况变动的元素,其他部分应保持原状
修改为

<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<title>DeepBIO</title>

icon的修改可以直接替换文件夹public下的favicon.ico文件

robots.txt

此文件是与爬虫签订的君子协议,规定了爬虫可以爬取的内容但不是强制要求,可根据实际情况做出修改。

项目核心文件

index.js

文件位于src文件夹下,是nodejs编译的源文件,其中引入了create-react-app创建的默认组件App.js,并将其渲染到上文提到的index.html文件中id=root的html节点。我们可以也应该将index.js中包含的渲染关系、组件等内容改写。
index.js文件的修改涉及到整个项目的核心架构,需要将整体架构大致明确后进行修改。

路由路径 + 组件结构

经过小组内多次讨论,项目的前端暂定有如下几个模块,并以ECMAScript Module的形式表示出来

  • 主页 HomePage
  • 功能选择 ServerSelect
  • 训练模型 ServerTrainHome
    • DNA模型训练 DNAServerForm
    • RNA模型训练 RNAServerForm
    • 蛋白质模型训练 ProteinServerForm
  • 序列分析 ServerPridictHome
    • DNA序列分析 DNAPredictForm
    • RNA序列分析 RNAPredictForm
    • 蛋白质/多肽链序列分析 ProteinPredictForm
  • 任务列表 JobHome
  • 结果展示 ResultHome
  • 关于 About
  • 参考文献 Reference

架构大致明确后,为了在App中使用React的路由,index.js中需要设置路由路径及各路径对应的React组件。
首先,先根据项目结构创建文件夹及对应的组件,如主页需要在pages/home下创建homePage.jsx文件,jsx文件全称为JavaScript Syntax Extension,是React组件的常见格式,也是编写组件的一种核心的语法。路径、文件名可以与项目结构不同,但是最好保持一个简单易懂的结构,方便引入组件。

对应组件文件创建后,需要在index.js中引入,以主页组件Home为例,使用

import HomePage from './pages/home/homePage';

此时,homePage.jsxexport default语句后的内容(即该jsx文件对外暴露的组件)在index.js中被注册为HomePage,可以在路由配置中使用

最后,在index.js中编写

const route = {
  path: "/", title: "Home", element: <Outlet />, children: [
    { title: "Home", icon: <HomeRounded />, index: true, element: <HomePage /> },
    {
      title: "Server", icon: <Storage />, path: "server", element: <Outlet />, children: [
        { title: "Server", index: true, element: <ServerSelect /> },
        {
          title: "Deep learning based prediction", path: "prediction", element: <ServerTrainHome />, children: [
            {
              title: "DNA", path: "dna", element: <Outlet />, children: [
                { index: true, element: <DNAServerForm /> },
              ]
            },
            {
              title: "RNA", path: "rna", element: <Outlet />, children: [
                { index: true, element: <RNAServerForm /> },
              ]
            },
            {
              title: "Protein", path: "protein", element: <Outlet />, children: [
                { index: true, element: <ProteinServerForm /> },
              ]
            },
          ]
        },
        {
          title: "Sequence functional annotation", path: "analysis", element: <ServerPredictHome />, children: [
            {
              title: "DNA", path: "dna", element: <Outlet />, children: [
                { index: true, element: <DNAPredictForm /> },
              ]
            },
            {
              title: "RNA", path: "rna", element: <Outlet />, children: [
                { index: true, element: <RNAPredictForm /> },
              ]
            },
            {
              title: "Protein", path: "protein", element: <Outlet />, children: [
                { index: true, element: <ProteinPredictForm /> },
              ]
            },
          ]
        },
      ]
    },
    { title: "Task List", icon: <AssignmentTurnedInRounded />, path: "tasks", element: <JobHome /> },
    { title: "Result", path: "result", element: <ResultHome />, maxWidth: "xl" },
    { title: "About", icon: <BadgeRounded />, path: "about", element: <About /> },
    { title: "Reference", icon: <FormatQuoteRounded />, path: "reference", element: <Reference /> },
  ]
}

此对象将组件、路径绑定起来,最后将其作为参数传入路由组件

import { HashRouter, useRoutes, useLocation, Outlet } from 'react-router-dom';
function Routes() {
  const location = useLocation()
  return (
    <Fragment>
      <Box flex={1}> // material ui提供的组件之一
        {useRoutes([route])} // 将route对象传入react路由
      </Box>
    </Fragment>
  )
}

渲染核心元素Index

上文提到的React默认组件App显然不需要,可以删除App.js App.css这两个与App组件相关的文件并在index.js中删掉App组件的引入import语句。

同时,在index.js中创建函数Index作为项目的核心组件(React的函数式组件)

function Index() {
  //根据项目需要设置material ui的项目主题、断点等参数

  const pageRef = useRef(null) //react
  return (
    <Provider store={stores}>
      <SnackbarProvider autoHideDuration={2000}> // 消息提示框的组件
        <HashRouter>
          <Header route={route} />
          <div className="main" ref={pageRef}>
            <Routes /> // 显示核心,渲染上文提到的Routes组件
          </div>
        </HashRouter>
      </SnackbarProvider>
    </Provider>
  )
}

在index.js文件的末尾覆盖React渲染

ReactDOM.render(
  <Index />,
  document.getElementById('root')
);

即完成项目代码结构的搭建,下面就可以开展相关组件的编写工作,且组件的变化只局限于组件内,不会干扰到项目的正常工作。

可以看出JSX强大的语法灵活性

感想

我本来对于前端框架Vue更熟悉一些,经过这段时间对React的学习,我逐渐掌握了React框架的渲染思路,同时也感受到严丝合缝的项目结构对项目代码可读性、可维护性的重要性。这一点上Vue相对有所欠缺,虽然也有模块化编程的思路(ES6标准提供),但是面对React JSX语法支持还是略显无力。我也增长了阅读文档、资料、开源代码的能力。下一步开展对具体组件的编写工作

发表评论