当前位置: 首页 > news >正文

百度竞价网站怎么做网络营销公司排行

百度竞价网站怎么做,网络营销公司排行,页面设计的标准有哪些,乡镇社区教育中心网站建设文章目录 一、项目起航:项目初始化与配置二、React 与 Hook 应用:实现项目列表三、TS 应用:JS神助攻 - 强类型四、JWT、用户认证与异步请求五、CSS 其实很简单 - 用 CSS-in-JS 添加样式六、用户体验优化 - 加载中和错误状态处理七、Hook&…

文章目录

    • 一、项目起航:项目初始化与配置
    • 二、React 与 Hook 应用:实现项目列表
    • 三、TS 应用:JS神助攻 - 强类型
    • 四、JWT、用户认证与异步请求
    • 五、CSS 其实很简单 - 用 CSS-in-JS 添加样式
    • 六、用户体验优化 - 加载中和错误状态处理
    • 七、Hook,路由,与 URL 状态管理
    • 八、用户选择器与项目编辑功能
    • 九、深入React 状态管理与Redux机制
    • 十、用 react-query 获取数据,管理缓存
    • 十一、看板页面及任务组页面开发
      • 1~3
      • 4~6
      • 7&8
      • 9&10
      • 11.排序乐观更新
      • 12.任务组页面 (上)


学习内容来源:React + React Hook + TS 最佳实践-慕课网


相对原教程,我在学习开始时(2023.03)采用的是当前最新版本:

版本
react & react-dom^18.2.0
react-router & react-router-dom^6.11.2
antd^4.24.8
@commitlint/cli & @commitlint/config-conventional^17.4.4
eslint-config-prettier^8.6.0
husky^8.0.3
lint-staged^13.1.2
prettier2.8.4
json-server0.17.2
craco-less^2.0.0
@craco/craco^7.1.0
qs^6.11.0
dayjs^1.11.7
react-helmet^6.1.0
@types/react-helmet^6.1.6
react-query^6.1.0
@welldone-software/why-did-you-render^7.0.1
@emotion/react & @emotion/styled^11.10.6

具体配置、操作和内容会有差异,“坑”也会有所不同。。。


一、项目起航:项目初始化与配置

  • 一、项目起航:项目初始化与配置

二、React 与 Hook 应用:实现项目列表

  • 二、React 与 Hook 应用:实现项目列表

三、TS 应用:JS神助攻 - 强类型

  • 三、 TS 应用:JS神助攻 - 强类型

四、JWT、用户认证与异步请求

  • 四、 JWT、用户认证与异步请求(上)

  • 四、 JWT、用户认证与异步请求(下)

五、CSS 其实很简单 - 用 CSS-in-JS 添加样式

  • 五、CSS 其实很简单 - 用 CSS-in-JS 添加样式(上)

  • 五、CSS 其实很简单 - 用 CSS-in-JS 添加样式(下)

六、用户体验优化 - 加载中和错误状态处理

  • 六、用户体验优化 - 加载中和错误状态处理(上)

  • 六、用户体验优化 - 加载中和错误状态处理(中)

  • 六、用户体验优化 - 加载中和错误状态处理(下)

七、Hook,路由,与 URL 状态管理

  • 七、Hook,路由,与 URL 状态管理(上)

  • 七、Hook,路由,与 URL 状态管理(中)

  • 七、Hook,路由,与 URL 状态管理(下)

八、用户选择器与项目编辑功能

  • 八、用户选择器与项目编辑功能(上)

  • 八、用户选择器与项目编辑功能(下)

九、深入React 状态管理与Redux机制

  • 九、深入React 状态管理与Redux机制(一)

  • 九、深入React 状态管理与Redux机制(二)

  • 九、深入React 状态管理与Redux机制(三)

  • 九、深入React 状态管理与Redux机制(四)

  • 九、深入React 状态管理与Redux机制(五)

十、用 react-query 获取数据,管理缓存

  • 十、用 react-query 获取数据,管理缓存(上)

  • 十、用 react-query 获取数据,管理缓存(下)

十一、看板页面及任务组页面开发

1~3

  • 十一、看板页面及任务组页面开发(一)

4~6

  • 十一、看板页面及任务组页面开发(二)

7&8

  • 十一、看板页面及任务组页面开发(三)

9&10

  • 十一、看板页面及任务组页面开发(四)

11.排序乐观更新

新建 src\utils\reorder.ts (这部分视频没有详细讲。。。之后项目中如果用到可以深挖一下):

/*** 在本地对排序进行乐观更新* @param fromId 要排序的项目的id* @param type 'before' | 'after'* @param referenceId 参照id* @param list 要排序的列表, 比如tasks, kanbans*/
export const reorder = ({fromId,type,referenceId,list,
}: {list: { id: number }[];fromId: number;type: "after" | "before";referenceId: number;
}) => {const copiedList = [...list];// 找到fromId对应项目的下标const movingItemIndex = copiedList.findIndex((item) => item.id === fromId);if (!referenceId) {return insertAfter([...copiedList], movingItemIndex, copiedList.length - 1);}const targetIndex = copiedList.findIndex((item) => item.id === referenceId);const insert = type === "after" ? insertAfter : insertBefore;return insert([...copiedList], movingItemIndex, targetIndex);
};/*** 在list中,把from放在to的前边* @param list* @param from* @param to*/
const insertBefore = (list: unknown[], from: number, to: number) => {const toItem = list[to];const removedItem = list.splice(from, 1)[0];const toIndex = list.indexOf(toItem);list.splice(toIndex, 0, removedItem);return list;
};/*** 在list中,把from放在to的后面* @param list* @param from* @param to*/
const insertAfter = (list: unknown[], from: number, to: number) => {const toItem = list[to];const removedItem = list.splice(from, 1)[0];const toIndex = list.indexOf(toItem);list.splice(toIndex + 1, 0, removedItem);return list;
};

编辑 src\utils\use-optimistic-options.ts(在之前写的配置中调用,完成乐观更新):

...
export const useReorderViewboardConfig = (queryKey: QueryKey) =>useConfig(queryKey, (target, old) => reorder({ list: old, ...target }));export const useReorderTaskConfig = (queryKey: QueryKey) =>useConfig(queryKey, (target, old) => {const orderedList = reorder({ list: old, ...target }) as Task[];return orderedList.map((item) =>item.id === target.fromId? { ...item, kanbanId: target.toKanbanId }: item);});

由于 task 的排序有可能是跨 面板 的,因此会复杂一些

查看效果,发现在拖拽到其他面板后,若是原面板为空,拖不回去了。。。因此需要为 DropChild 加一个最小高度

编辑 src\screens\ViewBoard\components\ViewboardCloumn.tsx:

...
export const ViewboardColumn = React.forwardRef<...>((...) => {...return (<Container {...props} ref={ref}>...<TasksContainer><Drop {...}><DropChild style={{minHeight: '5px'}}>...</DropChild></Drop><CreateTask kanbanId={viewboard.id} /></TasksContainer></Container>);
});
...

至此拖拽大功告成!

12.任务组页面 (上)

看板页面开发完,接下来是任务组页面

新建 src\types\TaskGroup.ts

export interface TaskGroup {id: number;name: string;projectId: number;// 开始时间start: number;// 结束时间end: number;
}

新建 src\utils\taskGroup.ts(与看板 Viewboard(kanban) 类似,可以复制后修改):

import { cleanObject } from "utils";
import { useHttp } from "./http";
import { TaskGroup } from "types/TaskGroup";
import { QueryKey, useMutation, useQuery } from "react-query";
import {useAddConfig,useDeleteConfig,
} from "./use-optimistic-options";export const useTaskGroups = (param?: Partial<TaskGroup>) => {const client = useHttp();return useQuery<TaskGroup[]>(["taskgroups", param], () =>client("epics", { data: cleanObject(param || {}) }));
};export const useAddTaskGroup = (queryKey: QueryKey) => {const client = useHttp();return useMutation((params: Partial<TaskGroup>) =>client(`epics`, {method: "POST",data: params,}),useAddConfig(queryKey));
};export const useDeleteTaskGroup = (queryKey: QueryKey) => {const client = useHttp();return useMutation((id?: number) =>client(`epics/${id}`, {method: "DELETE",}),useDeleteConfig(queryKey));
};

新建 src\screens\TaskGroup\utils.ts:

import { useProjectIdInUrl } from "screens/ViewBoard/utils";export const useTaskGroupSearchParams = () => ({projectId: useProjectIdInUrl(),
});export const useTaskGroupsQueryKey = () => ["taskgroups",useTaskGroupSearchParams(),
];

修改 src\types\Task.ts(属性字段需要和实际数据一致。。。):

export interface Task {id: number;name: string;projectId: number;processorId: number; // 经办人epicId: number; // 任务组(原 taskGroupId)kanbanId: number;typeId: number; // bug or tasknote: string;
}

编辑 src\screens\TaskGroup\index.tsx(之前新建路由时创建过,页面布局有一部分与看板相同,可以拿过来 src\screens\ViewBoard\index.tsx):

import { Row, ViewContainer } from "components/lib";
import { useProjectInUrl } from "screens/ViewBoard/utils";
import { useTaskGroups } from "utils/taskGroup";
import { useTaskGroupSearchParams, useTaskGroupsQueryKey } from "./utils";
import { Button, List, Modal } from "antd";
import dayjs from "dayjs";
import { useTasks } from "utils/task";
import { Link } from "react-router-dom";
import { TaskGroup } from "types/TaskGroup";
import { useState } from "react";export const TaskGroupIndex = () => {const { data: currentProject } = useProjectInUrl();const { data: taskGroups } = useTaskGroups(useTaskGroupSearchParams());const { data: tasks } = useTasks({ projectId: currentProject?.id });return (<ViewContainer><Row between={true}><h1>{currentProject?.name}任务组</h1><Button onClick={() => setEpicCreateOpen(true)} type={"link"}>创建任务组</Button></Row><Liststyle={{ overflow: "scroll" }}dataSource={taskGroups}itemLayout={"vertical"}renderItem={(taskGroup) => (<List.Item><List.Item.Metatitle={<Row between={true}><span>{taskGroup.name}</span><Button onClick={() => {}} type={"link"}>删除</Button></Row>}description={<div><div>开始时间:{dayjs(taskGroup.start).format("YYYY-MM-DD")}</div><div>结束时间:{dayjs(taskGroup.end).format("YYYY-MM-DD")}</div></div>}/><div>{tasks?.filter((task) => task.epicId === taskGroup.id).map((task) => (<Linkto={`/projects/${currentProject?.id}/viewboard?editingTaskId=${task.id}`}key={task.id}>{task.name}</Link>))}</div></List.Item>)}/></ViewContainer>);
};

查看页面效果,点击对应任务会跳转到看板并打开任务编辑窗口

编辑 src\screens\TaskGroup\index.tsx(新增删除任务组功能):

...
import { useDeleteTaskGroup, useTaskGroups } from "utils/taskGroup";export const TaskGroupIndex = () => {...const { mutate: deleteTaskGroup } = useDeleteTaskGroup(useTaskGroupsQueryKey());const confirmDeleteEpic = (taskGroup: TaskGroup) => {Modal.confirm({title: `确定删除项目组:${taskGroup.name}`,content: "点击确定删除",okText: "确定",onOk() {deleteTaskGroup(taskGroup.id);},});};return (<ViewContainer><Row between={true}>...</Row><Liststyle={{ overflow: "scroll" }}dataSource={taskGroups}itemLayout={"vertical"}renderItem={(taskGroup) => (<List.Item><List.Item.Metatitle={<Row between={true}><span>{taskGroup.name}</span><Button onClick={() => confirmDeleteEpic(taskGroup)} type={"link"}>删除</Button></Row>}description={...}/><div>...</div></List.Item>)}/></ViewContainer>);
};

查看页面,可以正常删除任务组(建议功能尝试放到完成创建功能之后再尝试,你懂的。。。)


部分引用笔记还在草稿阶段,敬请期待。。。


文章转载自:
http://enceinte.wqfj.cn
http://choreographist.wqfj.cn
http://strumae.wqfj.cn
http://inquisitor.wqfj.cn
http://slumbery.wqfj.cn
http://motmot.wqfj.cn
http://abram.wqfj.cn
http://caducity.wqfj.cn
http://voltammetry.wqfj.cn
http://harp.wqfj.cn
http://depeople.wqfj.cn
http://cumbric.wqfj.cn
http://effectively.wqfj.cn
http://avoidant.wqfj.cn
http://matara.wqfj.cn
http://dimer.wqfj.cn
http://enquiringly.wqfj.cn
http://mondain.wqfj.cn
http://preediting.wqfj.cn
http://contractible.wqfj.cn
http://expostulatory.wqfj.cn
http://skelter.wqfj.cn
http://sociogram.wqfj.cn
http://taupe.wqfj.cn
http://nrotc.wqfj.cn
http://rounded.wqfj.cn
http://nitroaniline.wqfj.cn
http://tola.wqfj.cn
http://abraxas.wqfj.cn
http://overclaim.wqfj.cn
http://invigorative.wqfj.cn
http://aeromechanical.wqfj.cn
http://synergamy.wqfj.cn
http://dulciana.wqfj.cn
http://krooman.wqfj.cn
http://therein.wqfj.cn
http://calicoed.wqfj.cn
http://pokie.wqfj.cn
http://calypsonian.wqfj.cn
http://mount.wqfj.cn
http://comprehensively.wqfj.cn
http://taconite.wqfj.cn
http://layard.wqfj.cn
http://caprification.wqfj.cn
http://venography.wqfj.cn
http://nonstriker.wqfj.cn
http://mensal.wqfj.cn
http://archbishop.wqfj.cn
http://octaroon.wqfj.cn
http://microammeter.wqfj.cn
http://conduit.wqfj.cn
http://podzolisation.wqfj.cn
http://authentically.wqfj.cn
http://remortgage.wqfj.cn
http://photokinesis.wqfj.cn
http://darkling.wqfj.cn
http://conically.wqfj.cn
http://oculonasal.wqfj.cn
http://boblet.wqfj.cn
http://appeared.wqfj.cn
http://pyrolater.wqfj.cn
http://contractility.wqfj.cn
http://troche.wqfj.cn
http://didacticism.wqfj.cn
http://sorter.wqfj.cn
http://yair.wqfj.cn
http://deoxygenization.wqfj.cn
http://parosmia.wqfj.cn
http://de.wqfj.cn
http://lobworm.wqfj.cn
http://palisade.wqfj.cn
http://embedded.wqfj.cn
http://abysmal.wqfj.cn
http://retinalite.wqfj.cn
http://sclerosing.wqfj.cn
http://deprecative.wqfj.cn
http://cyanic.wqfj.cn
http://dragging.wqfj.cn
http://mattery.wqfj.cn
http://colorcast.wqfj.cn
http://recapture.wqfj.cn
http://thoughtway.wqfj.cn
http://eustatic.wqfj.cn
http://wistaria.wqfj.cn
http://cimbalom.wqfj.cn
http://forspent.wqfj.cn
http://trigeminal.wqfj.cn
http://suburban.wqfj.cn
http://anselm.wqfj.cn
http://drollness.wqfj.cn
http://cryophysics.wqfj.cn
http://unwatched.wqfj.cn
http://brass.wqfj.cn
http://pep.wqfj.cn
http://flossy.wqfj.cn
http://transprovincial.wqfj.cn
http://nudnik.wqfj.cn
http://shaving.wqfj.cn
http://lola.wqfj.cn
http://gazob.wqfj.cn
http://www.hrbkazy.com/news/61524.html

相关文章:

  • 网上做家教兼职哪个网站网站怎么弄
  • 龙采做网站要多少钱网站关键词优化多少钱
  • 西安网站优化打开百度一下网页版
  • 西部数码网站管理助手 xp360搜索关键词优化软件
  • 网站建设 .北京蓝纤湖南正规关键词优化报价
  • 淄博网站建设费用聊城今日头条最新
  • 本地网站建设杭州百度百家号seo优化排名
  • 如何用付费音乐做视频网站网址大全导航
  • wordpress建站云平台新媒体运营是做什么
  • 如何制作免费的公司网站关于进一步优化当前疫情防控措施
  • 沈阳个人网站建设代理品牌网站seo服务商
  • 淘金企业网站建设国际最新消息
  • 北京政府网站建设企业网站seo哪里好
  • 怎么做网页模板展示网站友链购买有效果吗
  • 重置wordpress密码seo专业培训技术
  • 哪个网站可以做职业测试常用的网络推广方法有
  • 用dw做音乐网站百度在线使用网页版
  • 海尔网站建设水平北京有限公司
  • 山东省建设工程招标投标管理信息网官网鹤壁网站seo
  • 自定义优定软件网站建设武汉seo搜索引擎优化
  • 网站建设推广嵌入式培训班一般多少钱
  • 转运网站建设北京seo的排名优化
  • 一个网站锚文本可以做几个网络宣传的方法有哪些
  • 1000学习做网站贵吗热门seo推广排名稳定
  • 南宁网站推广¥做下拉去118cr网址制作
  • 收藏网站 js百度搜索网站排名
  • 网站商城微信支付宝支付宝支付接口郑州网站制作推广公司
  • 山西住房建设部网站seo的作用
  • 找人做效果土去那网站找太原seo快速排名
  • 国外 wordpress模板下载地址seo顾问阿亮博客