初始化一个react项目所需要做得一些事:以「纸记卡片 Paper MEMO」为例

以下内容算是对第一个 react 项目「纸记卡片 Paper MEMO」的一些技术总结,都是最基本的,部分内容可能另起文章记录,以备忘。

开始

首先安装 node.js,它是一个 exe 文件,直接从官网下载下来傻瓜安装即可。安装完成后打开 cmd 安装create-react-app

npm i -g create-react-app

安装 VS Code 并安装两个插件:

  1. Prettier – Code formatter(用来格式化代码)
  2. Simple React Snippets (用来专门补全 react 的代码)

在想要新建项目的文件夹打开 cmd,新建 react 项目,比如说这个项目叫做 react-app:

Create-react-app react-app

一些常用的命令,这些命令需要在项目文件夹下打开 cmd 运行:

npm start #预览项目
npm run build #编译成用于生产环境的静态文件

例如运行npm start 后浏览器会自动打开http://localhost:3000,可以预览。而运行npm run build可以生成用于生产环境的文件,这些文件会在build文件夹下,将这些文件上传到服务器或者虚拟主机均可。

以「纸记卡片 Paper MEMO」为例

「纸记卡片 Paper MEMO」项目中,除了开始的操作之外,还需要在环境中准备:

npm install @material-ui/core
npm install @material-ui/icons
npm install redux
npm install react-redux
npm install --save jspdf
npm install --save react-dropzone

「纸记卡片 Paper MEMO」项目使用了 Material-UI 组件库(下方涉及到样式库均为 Material-UI),其中使用了其默认的Dashboard 模板进行改造。src下的目录结构如下所示:

-src
--CreatPdf
---Pdf2.js
---Pdf4.js
---Pdf8.js
---Pdf16.js
---Pdf32.js
--Ppmemo
---Dashboard.js
---Emoji.js
---Helper.js
---listItems.js
---Title.js
--font
---font.js
--images
--store
---reducer.js

import 导入

以下是一些头部导入的示例:

//每次必须的
import React from "react";
//当需要用到useCallback和useEffect时
import React, { useCallback, useEffect } from "react";
//导入material-ui的组件
import Drawer from "@material-ui/core/Drawer";
//可以对组件的样式进行定制
import { makeStyles } from "@material-ui/core/styles";
//导入material-ui的icon
import MenuIcon from "@material-ui/icons/Menu";
//导入自己的组件
import Helper from "./Helper";
//导入自己的图片
import conjHelper from "../images/conjHelper.jpg";

makeStyles 和基础结构

Material-UI 中使用自定义样式时,需要先导入makeStyles。一个 react 的基本结构(react hooks)也如下所示:

  1. 开始的时候使用import导入。
  2. function 函数可以放一些自己想做的事情。
  3. makeStyle 自定义样式(仅限 Material-UI)。
  4. export default function Upload() {}可以理解为主函数,必不可少。

//可以对组件的样式进行定制
import { makeStyles } from "@material-ui/core/styles";
import Helper from "./Helper";

function Copyright() {
  //做一些想做的事情
  return (//返回一些想返回的东西)
}

const useStyles = makeStyles(() => ({
  text: {
    textAlign: "center",
    position: "relative",
    top: "40%",
  },
}));

export default function Upload() {
  const classes = useStyles();

  return (
    <div>
        <Paper className={classes.text}>
            <Helper/>
            <Copyright />
        </Paper>
    </div>
}

switch

switch 比较常用,可以代替大量的if else,但是注意不要忘了default,用于默认返回一些东西:

function getStepContent(stepIndex) {
  switch (stepIndex) {
    case 0:
      return "阅读上述准备步骤后,点击下一步";
    case 1:
      return "选择一份文件并上传(当且仅当上传符合条件的txt文件后,才能进行下一步)";
    case 2:
      return "调整纸张设置并生成卡片,点击“下载”获得PDF文件";
    case 3:
      return "";
    default:
      return "Unknown stepIndex";
  }
}

按钮和判断

在下方的例子中:

  1. successedData为 false 时(注意需要使用全等===),按钮不可用。
  2. 当用户点击按钮时onClick,执行handleNext
export default function Dashboard() {
  const handleNext = () => {
    setActiveStep((prevActiveStep) => prevActiveStep + 1);
  };
  return (
    <Button
      variant="contained"
      color="primary"
      onClick={handleNext}
      className={classes.buttonArea}
      disabled={successedData === false}
    >
      {activeStep === steps.length - 1 ? "下载" : "下一步"}
    </Button>
  );
}

下方是另一种判断的使用方式:

<div className={classes.fixedHeight100}>
  {activeStep === steps.length ? <div></div> : <div></div>}
</div>

React 懒加载

打开的网页的一开始可能不需要加载所有的网站内容,这样可以节省加载时间,所以这里需要使用懒加载。

  1. 下方的import写在开头那堆 import 文件下方,凡是不能和正常的 import 文件混起来写。
  2. React.Suspense可以写一些在等待懒加载时所加载的一些提示语、进度条等。
const Pdf2 = React.lazy(() => import("../CreatePdf/Pdf2"));

const CreatPdf = () => {
  return (
    <React.Suspense
      fallback={
        <div>
          <CircularProgress />
          <Typography variant="h6">等待下载中...这可能需要一些时间</Typography>
        </div>
      }
    >
      <Pdf2 />
    </React.Suspense>
  );
};

setState

setState用的比较多,用来更新 ui 上显示的数据。

  1. 有个变量叫Successed,初始值为""
  2. displayUploadData等于undefined时,将Successed的值设为"❌文件不符合要求"
const [Successed, setSuccessed] = React.useState("");

if (displayUploadData === undefined) {
  setSuccessed("❌文件不符合要求");
}
  1. 有个变量叫format,初始值为一个对象。
  2. handleChangeFormat函数中将 format 里面的 format 设置为一个别的值。
  3. 和上面的例子一样,setFormat会设置原有format对象里所有的值,但是要注意写法。
const [format, setFormat] = React.useState({
  format: "Pdf16",
  font: "fontFz",
  fontSizeA: "fontMiddle",
  fontSizeB: "fontMiddle",
  cardNum: true,
});

const handleChangeFormat = (event) => {
  format.format = event.target.value;
  setFormat({ ...format }); //就是要写成这样,不然无法更新;这样format就变为了event.target.value里的值
};

显示图片

//导入自己的图片
import conjHelper from "../images/conjHelper.jpg";
<img src={conjHelper} alt="" className={classes.imageStyle} />;

redux 和 react-redux

假设文件目录如下:

-src
--CreatPdf
---Pdf2.js
--Ppmemo
---Dashboard.js
---Emoji.js
---Upload.js //从这里传数据
--font
---font.js
--images
--store  //新建
---reducer.js  //新建

首先在根目录新建一个文件夹和文件叫做store/reducer.js,该文件内的内容如下:

const initialState = {
  content: "欢迎使用ppmemo-https://xd.sh.cn",
  format: {
    format: "Pdf16",
    font: "fontFz",
    fontSizeA: "fontMiddle",
    fontSizeB: "fontMiddle",
    cardNum: true,
  },
  successedData: false,
};

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case "ADD_FORMAT": {
      const newTemp = action.format;
      return {
        ...state,
        format: newTemp,
      };
    }
    case "ADD_CONTENT": {
      const newTemp = action.content;
      return {
        ...state,
        content: newTemp,
      };
    }
    default:
      return state; //在 default 情况下返回旧的 state。遇到未知的 action 时,一定要返回旧的 state。
  }
};

export default reducer;

在组件文件Upload.js中导入:

import { useDispatch } from "react-redux"; //新版里导入useDispatch和useSeletor
  // 用 useDispatch 產生 dispatch 方法,dispatch用来给reducer送数据
  const dispatch = useDispatch();
  const storeUploadData = (uploadData) => {
    dispatch({
      type: "ADD_CONTENT",
      content: uploadData,
    });
  };

  //使用上述函数
  storeUploadData(uploadData);

如果更新的是对象,比如上文中的format就有5个对象元素,更新其中的font

  const dispatch = useDispatch();
  const storeFormat = (format) => {
    // 用法一樣
    dispatch({
      type: "ADD_FORMAT",
      format: format,
    });
  };

  //使用上述函数,比方说更新对象format中的font
  const handleChangeFont = (event) => {
    format.font = event.target.value;
    setFormat({ ...format }); //就是要写成这样,不然无法更新
    storeFormat(format);
  };

react hooks

【待更新】

jsPDF

【待更新】

react-dropzone

【待更新】

暂无评论

发送评论 编辑评论


				
上一篇
下一篇