问卷星项目
样式层
1.问卷列表样式问题

1 2 3 4 5 6 7 8 9 10 11 12 13
   | .title{     display: flex;
      .left{         flex:1;     }
      .right{         flex:1;         text-align: right;         font-size: 12px;     } }
  | 
 
这段CSS代码定义了一个名为.title的类,用于设置标题的样式。标题由两部分组成:.left和.right。
display: flex:将.title设置为flex布局,使得其子元素可以沿主轴方向排列。
 
.left:设置.left的flex属性为1,使得其占据剩余空间的比例为1:1。同时,设置.left的font-size为12px。
 
.right:设置.right的flex属性为1,使得其占据剩余空间的比例为1:1。同时,设置.right的text-align为right,使得文本右对齐。设置.right的font-size为12px。
 
注意:这段CSS代码主要用于设置标题的样式,使得标题中的左右两部分可以沿主轴方向排列,并且左右两部分可以分别设置不同的样式。
2.首页居中设计

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
   | .container {     height: calc(100vh - 64px - 65px);     display: flex;     flex-direction: column;     justify-content: center;     align-items: center;     background-image: linear-gradient(to right, #4facfe 0%, #00f2fe 100%);
      .info {         text-align: center;
          button {             height: 60px;             font-size: 24px;         }     } }
  | 
 
路由层
开发过程

路由设计

使用路由和layout实现页面

/router/index.tsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
   | const router = createBrowserRouter([     {         path:'/',         element:<MainLayout />,         children:[             {                 path:'/',                 element:<Home />,             },             {                 path:'login',                 element:<Login />,             },             {                 path:'register',                 element:<Register />,             },             {                 path:'manage',                 element:<ManageLayout />,                 children:[                     {                         path:'list',                         element:<List />,                     },                     {                         path:'trash',                         element:<Trash />,                     },                     {                         path:'star',                         element:<Star />,                     }                 ]
              },             {                 path:'*',                 element:<NotFound />,             } ,         ]     },{         path:'question',         element:<QuestionLayout />,         children:[             {                 path:'edit/:id',                 element:<Edit />,
              },             {                 path:'stat/:id',                 element:<Stat />,             }         ]     }, ])
  export default router;
   | 
 
ManageLayout.tsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   |  import React, { FC } from "react"; import { Outlet } from "react-router-dom"; import styles from './ManageLayout.module.scss' const ManageLayout: FC = () => {   return (     <div className={styles.container}>       <div className={styles.left}>         <button>创建问卷</button>         <br></br>         <a href="#">我的问卷</a>         <br></br>         <a href="#">星标问卷</a>         <br></br>         <a href="#">回收站</a>       </div>       <div className={styles.right}>         <Outlet />       </div>     </div>   ); }; export default ManageLayout;
 
 
  | 
 
路由跳转的方式
1.useNavigate跳转,常用于按钮

2.Link跳转,常用于超链接

路由传参的方式
1.useParams传参,常用于组件

2.useSearchParams传参,常用于搜索

组件库层
安装使用antd

在 create-react-app 中使用 - Ant Design (antgroup.com)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
   | import React, { FC } from "react"; import { Outlet } from "react-router-dom"; import { Layout } from "antd"; import styles from "./MainLayout.module.scss";
  const { Header, Content, Footer } = Layout; const MainLayout: FC = () => {   return (     <Layout>       <Header className={styles.header}>         <div className={styles.left}>Logo</div>         <div className={styles.right}>登录</div>       </Header>       <Layout className={styles.main}>         <Content>           <Outlet />         </Content>       </Layout>       <Footer className={styles.footer}>         问卷星 ©2024-present. Created by Heibancha       </Footer>     </Layout>   ); }; export default MainLayout;
 
  | 
 
使用组件图标

组件库样式玩出花

根据路由路径来渲染按钮样式

首页制作


404页面制作

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   | import React, { FC } from 'react' import { useNavigate } from 'react-router-dom' import { Result, Button } from 'antd' import { MANAGE_INDEX_PATHNAME } from '../router'
  const NotFound: FC = () => {   const nav = useNavigate()
    return (     <Result       status="404"       title="404"       subTitle="抱歉,您访问的页面不存在"       extra={         <Button type="primary" onClick={() => nav(MANAGE_INDEX_PATHNAME)}>           返回首页         </Button>       }     ></Result>   ) }
  export default NotFound
 
  | 
 
问卷列表页面重构

标星问卷页面制作


回收站页面制作
表格形式渲染数据



rowKey解决表格key标识问题

可以把JSX片段定义为一个变量,再嵌入


搜索组件开发

下面主要考虑的是搜索后对路由的变化和页面刷新后的处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
   | import React, { FC, useState,useEffect } from "react"; import { Input } from "antd"; import { ChangeEvent } from "react"; import { useNavigate,useLocation,useSearchParams } from "react-router-dom"; import { LIST_SEARCH_PARAM_KEY } from "../constant"; const { Search } = Input; const ListSearch: FC = () => {     const nav = useNavigate()     const {pathname} = useLocation()     const [value, setValue] = useState('')          const [searchParams] = useSearchParams()     useEffect(() => {         const curVal =  searchParams.get(LIST_SEARCH_PARAM_KEY) || ''         setValue(curVal)     }, [searchParams])     function handleSearch(value:string) {         nav({             pathname,             search:`${LIST_SEARCH_PARAM_KEY}=${value}`         })     }
      function handleChange(e:ChangeEvent<HTMLInputElement>) {         setValue(e.target.value)     }   return <Search  placeholder="请输入关键字" allowClear value={value} onChange={handleChange} onSearch={handleSearch} style={{ width: '260px' }}/> } export default ListSearch;
 
  | 
 
搜索,分页,列表的展示都依赖于路由url,这样更同一

注册页面开发
主要是对样式和排版和表单结构的开发

登录页面开发
主要是对 “记住我” 功能的开发

记住我主要用到两部分开发
一部分是保存,获取,删除本地存储的操作路线

另一部分是在页面刷新或组件变化时将本地存储数据存放到表单中的部分

表单校验
注册的用户名的表单校验:

注册的确认密码的表单校验:

Mock层
使用craco.js扩展webpack配置


使用Restful API规则设计

axios路由拦截器统一处理data和errno

处理创建问卷请求功能和由于网络请求延迟,防止多次调用创建问卷请求,添加状态处理

处理获取问卷详情功能
使用第三方Hook useLoadQuestionData封装公共逻辑 处理Loading和数据返回
使用useRequest


给列表添加搜索功能

partial的使用  -某个类型的一部分

