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

网站建设的客户给人做设计的网站

网站建设的客户,给人做设计的网站,包装设计案例,中国网站建设公司 排名React 项目结构小结 简单的记录一下目前 React 项目用的依赖和实现 摸索了大半年了大概构建一套用起来还算轻松的体系……#xff1f;基本上应该是说可以应对大部分的项目了 使用的依赖 目前项目还在 refactoring 的阶段#xff0c;所以乱得很#xff0c;这里是新建一个…React 项目结构小结 简单的记录一下目前 React 项目用的依赖和实现 摸索了大半年了大概构建一套用起来还算轻松的体系……基本上应该是说可以应对大部分的项目了 使用的依赖 目前项目还在 refactoring 的阶段所以乱得很这里是新建一个空的项目作为案例package.json 中新增添的依赖如下 {dependencies: {reduxjs/toolkit: ^1.9.7,ui-framework/keycloak-auth: ^4.0.0,axios: ^1.6.0,dayjs: ^1.11.10,lodash: ^4.17.21,react-redux: ^8.1.3,react-router-dom: ^6.18.0,redux-logger: ^3.0.6,styled-components: ^6.1.0,uuid: ^9.0.1} }版本不一定是最新的这个取决于我们的 nexux 库更新的有多勤快 主要归类如下 状态 reduxjs/toolkit 这是主要的管理部分RTK(Redux Toolkit) 是迭代后的版本 react-redux RTK 的依赖 redux-logger(可选) 用来查看 state 变化的插件 API 相关 axios 路由 其实可以的话是想找一下依赖看看有没有把路由归并到 redux 管理的实现之前看到的一些实现要么是 v5 的v6 不支持要么就是 v6 可以支持但是比较 buggy现在暂时没什么时间做这个晚点再折腾 react-router-dom 验证 keycloak-auth 这是一个登录的依赖token、profile 等会通过 keycloak-auth 返回 UI 公司内部其实有实现自己的 UI 库所以我就放两个底层用的依赖。其他关于 radio 之类的都是项目内部实现的 styled-components CSS-in-JS react-table react-table 本身是一个 headless 的库需要具体实现 UI react-select 这个比较方便的一点在于可以使用 async dropdown即通过点击 load more 或者 scroll 事件可以触发 API 调用 搭配好 pagination 的 query 可以比较好的提升用户体验 util 相关 dayjs 取代 momentjs uuid 主要用在 API 调用方面有的情况后端返回的 id 是 UUID lodash 底层用的还是 create-react-app主要是因为脚手架一来确实方便升级也可以直接通过升级 react-script 进行集成管理。二来我们的项目需求并没有复杂到需要将 webpack 单独拆出来做对应的优化等 基础结构 目前想要实现的结构如下 components 这里放置了一些封装好的 UI也就是我们根据自己内部的业务需求实现的一些 wrapper主要的类型有button, modal, layout, table 等 constants 这里是一些共用的逻辑这个里面的分类是按照 model 进行的分类 我们的项目是比较强类型的而且是 2b 业务所以主要就是表单表格的功能而每个表单/表格有需要有独立的 structure 传到 UI 库中形成对应的结构因此每个 model 对应的 structure 可以保存在 constant 中 另外一些可以保存的常量有 model 的类型这一块目前放到 types 里不过建于 types 对 TS 来说是生成 .d.ts 的文件的地方所以这个迟早是要修改的 pages 每一个渲染的页面 store redux store 的相关管理 types 目前用来放 model 的 type不过按照上面说的想要移到 const 中 utils 一些相关的 helpers包括环境、date、entity(model) 之类的 一些实现 其实主要还是 redux 相关的部分的修改其他部分要么就是之前已经写过笔记了要么就是跟具体业务相关的这里不太好记 react router dom v5 的使用[React 基础系列] React Router 的基本应用 和 v6 的升级React Router DOM 升级到 v6 后的一些报错信息 就目前来说我们还是待在 v5 没有动不过之后我需要对已经实现的 Router 进行一个重构到时候会实现一下升级 v6不过按照计划来说这也是明年二/三月份之后的事情…… 现在到明年二/三月份主要还是需要将所有的 page 转成 redux-based redux Redux 的使用其实之前也有写过大概如下 Redux Toolkit 调用 API 的四种方式[]async thunk 解决 API 调用的依赖问题(https://goldenaarcher.blog.csdn.net/article/details/129002505)Redux 错误处理 这里不会太进入细节简单的说一下每个 slice 里面的简单实现以及 pages 中的 component 怎么调用的基本结构大致如下 index.ts 这里代码其实没什么好变的基本上是一个万能模板了 import {configureStore,EnhancedStore,ThunkDispatch,AnyAction,Store, } from reduxjs/toolkit; import { TypedUseSelectorHook, useDispatch, useSelector } from react-redux; import logger from redux-logger; import reducers from ./slices;// reference: https://stackoverflow.com/questions/70143816/argument-of-type-asyncthunkactionany-void-is-not-assignable-to-paramete// 1. Get the root states type from reducers export type RootState ReturnTypetypeof store.getState;// 2. Create a type for thunk dispatch export type AppThunkDispatch ThunkDispatchRootState, any, AnyAction;// 3. Create a type for store using RootState and Thunk enabled dispatch export type AppStore OmitStoreRootState, AnyAction, dispatch {dispatch: AppThunkDispatch; };export const store: EnhancedStore configureStore({reducer: reducers,middleware: (getDefaultMiddleware) getDefaultMiddleware({serializableCheck: false,}).concat(logger), });// you can also create some redux hooks using the above explicit types export const useAppDispatch () useDispatchAppThunkDispatch(); export const useAppSelector: TypedUseSelectorHookRootState useSelector;useAppDispatch 和 useAppSelector 这个因为类型检查的关系使用 TS 的前提下几乎是必须的我之前也有一篇笔记讨论过这个。 helper func 我们实现了一个 createAsyncThunk 的 wrapper主要用来处理 AppThunkDispatch 需要重复提供类型问题代码如下 import { createAsyncThunk, createAction } from reduxjs/toolkit; import { AppThunkDispatch, RootState } from ../;export const createAppAsyncThunk createAsyncThunk.withTypes{state: RootState;dispatch: AppThunkDispatch;rejectValue: string;extra: { s: string; n: number }; }();slice/index.ts slice/index.ts 主要就是用来集成一堆的 reducer 让 store 去使用同时导出所有的 actions这样让其他地方的 import 干净一些大致代码如下 import { example } from ./slices/exampleSlice;const reducers {example, };export default reducers;export * from ./slices/exampleSlice;slice 这里的 slice 主要是 API 的操作代码大致如下 export type IExampleSlice {loading: boolean;data: any[];error: null | SerializedError; };const initialState: IExampleSlice {loading: false,data: [],error: null, };const uri ;const exampleSlice createSlice({name: modal,initialState,reducers: {clearState() {return initialState;},},extraReducers(builder) {builder.addCase(fetchExample.pending, () {return {...initialState,isLoading: true,};});builder.addCase(fetchExample.fulfilled, (state, { payload }) {// process payload});builder.addCase(fetchExample.rejected, (state, action) {console.error(action.error);state.error action.error;});}, });export const fetchExample createAppAsyncThunkany,{ payload: Partialany },{ state: RootState } (${uri}/post, async ({ payload }, { dispatch, getState }) {const res await wrappedFetchMethod();return res; });export const { clearState } exampleSlice.actions; export const example exampleSlice.reducer;其中 IExampleSlice 可以使用 generics 单独抽出来如 export type IGenericsSliceT {loading: boolean;data: T[];error: null | SerializedError; };type ExampleModel {id: string;name: string; };export type IExampleSlice IGenericsSliceExampleModel;我们项目就是将 API 单独抽出来进行了封装如果 slice 内有其他需要合并的属性在定义 ISthSlice 的时候会使用 进行合并 其他 slice 其他的 slice 比较灵活可以根据需求单独神明 type 并且进行返回。 每个 slice 有对应定义的 type 还是挺重要的尤其是之后 Component 中调用的时候可以比较方便的提供 intellisense RTKQ 目前的项目因为数据量的关系(没有做 pagination并且用户要求不做 pagination)所以决定不使用 RTKQ 在完成 CUD 操作后直接重新拉去数据 不过 RTK 可以 cache query并且在对应的 query 中对应的功能 也就是一旦出发 CUD 操作自动调用 retrieve 操作不需要手动在 await 操作中实现。这一点对于原子性要求更高的 2c 项目中很有用并且这个功能也取代了一些 redux-saga 可以实现的功能这也是为什么我没有考虑引入 saga 的原因 组件调用 slice 大致如下 import React, { useEffect } from react;import { useAppDispatch, useAppSelector, RootState } from ../store; // 所有导出都通过 slices/index因此相对而言 import 可以稍微干净一些 import { IExampleSlice, fetchExample } from ../store/slices;const Example () {const dispatch useAppDispatch();const { data, error, loading } useAppSelectorIExampleSlice((state: RootState) state.example);const apiCall async () {console.log(data, error, loading);const res await dispatch(fetchExample({payload: {id: ,},}));if (res.meta.requestStatus fulfilled) {// do sth}};useEffect(() {apiCall();}, []);return divExample/div; };export default Example;提供一些对于 payload 的检查还是有好处的比如 CRUD 中的操作主要都是对于对应的模型操作因此将上面的 payload 定义改成 Example 的模型TS 也可以自动对其进行静态检查 useAppSelector 中的类型 主要也是为了 intellisense如过不提供 IExampleSlice返回值如下 又或者是一些比较小的 typo如果不提供类型TS 是抓不出来的 提供后 导出方式 这里还是推荐使用 useAppSelector(state state.someState) 的方式这个是为了 performance直接返回整个 state 可能会引起不必须的渲染 错误处理 这个其实之前的笔记有提这里再说一下好了 如果是异步操作通过 asnc/await 可以直接获取 request 的结果这样就可以根据接过去具体更新 UI 了 如 操作成功关闭 modal 操作失败继续维持 modal 的开启状态 同时根据返回的 error在 UI 生成对应的错误信息 总结 其实大体上主要还是 redux 的配置比较多一些其他部分都挺灵活的而且和业务绑定的比较多我也不方便说说了也不一定有参考意义 项目的结构是一个比较风格化的东西我用的比较喜欢的风格 有点变态的说已经把这个项目变成了我喜欢的样子…… 并不代表这一定是一门项目会用的风格这是 react 的优点也是缺点 完成 redux 部分的 refactor 之后下一步考虑的就是使用 lerna 对项目升级做成一个 micro-frontend 的项目。这也是基于项目本身的特性决定的我们的项目是一个多地区使用的网页应用并且不同地区对于想要渲染的数据、显示的页面会有不同的需求。目前的实现就是一旦打包了所有的东西全都打包 ship 出去不过操作起来还是不太方便 我的构想是 将所有的 constant/util/components/slices 打包成一个共享的 module每个地区根据不同的需求 调用不同的 reducer生成只包含所需数据的 store实现对应的页面 最后形成一个像 venn diagram 的结构 而不是将所有的代码打包到一起 ship 出去
http://www.eeditor.cn/news/124743/

相关文章:

  • 网站开发年薪wordpress 第三方应用
  • 网站建设概要设计怎么写wordpress缩略图采集火车头
  • 深圳光明新区网站建设顺企网杭州网站建设
  • 国外免费网站域名服务器贷款做网站
  • 建设钓鱼网站发软文
  • 南昌网站免费制作设计网站的企业
  • 建筑工人招聘网站怎么做怎么自己开发软件
  • 四川餐饮网站建设集团网站定制
  • 外贸建站行业好做吗大良网站建设如何
  • 网站服务器站点是什么意思网站的分页效果怎么做
  • 福建巢网站建设seo的工作流程
  • 关于网站建设的论文题目it运维管理软件排名
  • 长沙网站备案拍照点wordpress屏蔽广告
  • 制作网站软件免费代理网址是什么意思
  • wap网站开发教材住房和城乡建设部网站投诉电话
  • 许昌工程建设信息网站网站要怎么做吸客户引眼球
  • 做pc端网站行情广州网站建设高端网
  • 深圳网站策划网站后台管理系统ie8用不了
  • 网站模版建设教程wordpress ip 地址修改
  • 免费建网站无广告icp备案 网站首页
  • 易企网络网站建设互联网站备案手续
  • 大连网络建站模板网站平台延展性
  • 沈阳做网站开发公司网站设计开发维护
  • 网站搭建入门程序制作软件
  • 宁波北仑网站网页建设某公司的网站建设的资金预算书
  • 湖南常德广宇建设网站信誉好的宜昌网站建设
  • 西安网站建设价格旅游网站模板图片
  • 昆明建设银行纪念币预约网站国家建设工程信息网站
  • 网站手机版方案wordpress全部文件夹
  • 极路由4 做网站wordpress 汉化模版