react+typescript+umi+dva+antd

简介: react+typescript+umi+dva+antd


背景

  • React
    前端三大框架之一。
  • typescript
    javascript的超集
  • Dva
    由阿里架构师 sorrycc 带领 team 完成的一套前端框架,在作者的 github 里是这么描述它的:”dva 是 react 和 redux 的最佳实践”。
  • Antd
    是阿里的一套开箱即用的中台前端/设计解决方案,UI框架。
  • Umi
    一套可插拔的企业级 react 应用框架,同样由dva作者 sorrycc 完成。他在Umi中引入了 UI 工具 antd,打包工具 roadhog,路由 react-router和状态管理器 dva,做到了可插拔机制。

创建一个umi应用

  1. 先安装node,再创建一个项目文件夹,通过脚手架创建umi项目
npx @umijs/create-umi-app

  1. 安装依赖
npm i
  1. 运行项目
npm run start

umi应用的路由

配置路由

在配置文件.umirc.ts中通过 routes 进行配置,格式为路由信息的数组。

routes: [
  { path: '/', component: '@/pages/Index' },
  { path: '/User', component: '@/pages/User' },
],

路由配置工程化

为了让代码更工程化,我们可以将路由配置单独拆分成一个文件

router.tsx

const router: any = [
  { path: '/', component: '@/pages/Index' },
  { path: '/User', component: '@/pages/User' },
]
export default router;

.umirc.ts

import { defineConfig } from 'umi';
import router from '@/router/router'; // 引入路由配置文件
export default defineConfig({
  nodeModulesTransform: {
    type: 'none',
  },
  routes: router,
});

约定式路由

除配置式路由外,Umi 也支持约定式路由。约定式路由也叫文件路由,就是不需要手写配置,文件系统即路由,通过目录和文件及其命名分析出路由配置。

备注:约定式路由要先注释.umirc.ts里的routes配置

路由跳转

import { history } from 'umi';
// 跳转到指定路由
history.push('/list');
// 带参数跳转到指定路由
history.push('/list?a=b');
history.push({
  pathname: '/list',
  query: {
    a: 'b',
  },
});
// 跳转到上一个路由
history.goBack();

示例

Index.tsx

import React, { Component } from 'react'
import { history } from 'umi';
import styles from '@/assets/Style/Index.less'; // css module
export default class Index extends Component {
  // 路由跳转不带参数
  toLogin() {
    history.push('/login');
  }
  // 路由跳转带参数
  toLoginWithParameter() {
    history.push({
      pathname: '/login',
      query: {
        a: 'b',
      },
    })
  }
  render() {
    return (
      <div>
        <div className={styles.title}>首页</div>
        <div onClick={this.toLogin}>跳转不带参数</div>
        <div onClick={this.toLoginWithParameter}>跳转带参数</div>
      </div>
    )
  }
}

User.tsx

import React, { Component } from 'react'
export default class User extends Component {
  constructor(props: any) {
    super(props);
    console.log(props.location.query) // 打印路由参数
  }
  render() {
    return (
      <div>
        <h1 className={styles.title}>User</h1>
      </div>
    )
  }
}

安装插件集@umijs/preset-react

@umijs/preset-react是包含antd,dva等一系列插件的插件集,由于使用指令npx @umijs/create-umi-app创建的项目会自动添加此插件,所以之后不需要再安装@umijs/preset-react插件集包含的插件,否则启动项目的时候会报错

umi+antd

安装了插件集@umijs/preset-react之后,无需再做任何配置,直接可以按需加载antd并在组件中使用

import React, { Component } from 'react'
import { history } from 'umi';
import { Button } from 'antd'; // 引入antd组件
import styles from '@/assets/Style/Index.less'; // css module
export default class Index extends Component {
  // 路由跳转不带参数
  toUser() {
    history.push('/User');
  }
  // 路由跳转带参数
  toUserWithParameter() {
    history.push({
      pathname: '/User',
      query: {
        a: 'b',
      },
    })
  }
  render() {
    return (
      <div>
        <div className={styles.title}>首页</div>
        <Button type="primary" onClick={this.toUser}>跳转不带参数</Button>
        <Button type="primary" onClick={this.toUserWithParameter}>跳转带参数</Button>
      </div>
    )
  }
}

umi+dva

安装了插件集@umijs/preset-react之后,无需再做任何配置,直接可以使用dva

  1. 创建models目录以及model文件userInfo.tsx
import { Effect, ImmerReducer, Reducer, Subscription } from 'umi';
export interface UserInfoModelState {
  name: string;
  age: number;
}
export interface UserInfoModelType {
  namespace: 'userInfo';
  state: UserInfoModelState;
  effects: {
    query: Effect;
  };
  reducers: {
    save: Reducer<UserInfoModelState>;
    changeName: Reducer<UserInfoModelState>;
    // 启用 immer 之后
    // save: ImmerReducer<UserInfoModelState>;
  };
  subscriptions: { setup: Subscription };
}
const UserInfoModel: UserInfoModelType = {
  namespace: 'userInfo',
  state: {
    name: '张三',
    age: 20,
  },
  effects: {
    *query({ payload }, { call, put }) {
    },
  },
  reducers: {
    save(state, action) {
      return {
        ...state,
        ...action.payload,
      };
    },
    changeName(state, action) {
      return {
        ...state,
        ...action.payload,
      };
    },
    // 启用 immer 之后
    // save(state, action) {
    //   state.name = action.payload;
    // },
  },
  subscriptions: {
    setup({ dispatch, history }) {
      return history.listen(({ pathname }) => {
        if (pathname === '/') {
          dispatch({
            type: 'query',
          })
        }
      });
    }
  }
};
export default UserInfoModel;
  1. 组件中使用
  • class组件中使用
import React, { Component } from 'react'
import { connect, UserInfoModelState, Loading } from 'umi';
const connect1: any = connect;
@connect1(({ userInfo, loading }: { userInfo: UserInfoModelState; loading: Loading }) => ({
  userInfo,
  // dva-loading可以自动处理loading状态
  loading: loading.models.index,
}))
export default class User extends Component<any, any> {
  constructor(props: any) {
    super(props);
    console.log(props);
    this.state = {
      username: props.userInfo.name
    }
  }
  // 调用userInfo模块的reducers里的changeName方法
  private changeName = () => {
    const { dispatch } = this.props;
    dispatch({
        type: 'userInfo/changeName',
        payload:{
          name: '李四'
        }
    })
  }
  render() {
    return (
      <div>
        <div onClick={this.changeName}>更改用户名</div>
        <div className="title">用户名{this.props.userInfo.name}</div>
      </div>
    )
  }
}
  • 函数式组件中使用
import React, { FC } from 'react';
import { UserInfoModelState, ConnectRC, Loading, connect } from 'umi';
interface PageProps {
  userInfo: UserInfoModelState;
  loading: boolean;
}
const IndexPage: FC<PageProps> = (props) => {
  const handleClick = () => {
    const { dispatch } : any = props;
    dispatch({
      type: 'userInfo/changeName',
      payload:{
        name: '李四'
      }
    })
  }
  return (
    <div>
      <div onClick={handleClick}>更改用户名</div>
      <div className="title">用户名{props.userInfo.name}</div>
    </div>
  )
};
export default connect(({ userInfo, loading }: { userInfo: UserInfoModelState; loading: Loading }) => ({
  userInfo,
  loading: loading.models.index,
}))(IndexPage);
  • 项目目录

主要文章参考

https://www.icode9.com/content-4-652359.html

https://www.cnblogs.com/llcdbk/p/13029996.html

https://www.cnblogs.com/crazycode2/p/8593143.html

https://www.jianshu.com/p/86bd9fc0a219

https://segmentfault.com/q/1010000014835057

https://blog.csdn.net/YMX2020/article/details/106674097

https://blog.csdn.net/SCU_Cindy/article/details/82432971

初次尝试,摸坑永不止步,还有以下文章也参考了一下,拓展思路

https://www.cnblogs.com/jiawei-Wang/p/11400848.html

https://segmentfault.com/a/1190000021272819?utm_source=tag-newest

https://zhuanlan.zhihu.com/p/69200639

https://www.yuque.com/umijs/umi/dvamodels

https://www.codercto.com/a/25627.html

https://blog.csdn.net/deletGlobal/article/details/106183217

https://blog.csdn.net/YMX2020/article/details/106674097

https://zhuanlan.zhihu.com/p/92617879

http://www.caotama.com/294655.html

https://www.cnblogs.com/winfred/p/8216650.html

https://www.jianshu.com/p/21f8ed30e761

https://www.cnblogs.com/axel10/p/8503782.html

https://www.jianshu.com/p/81a5d4371f81

https://blog.csdn.net/sllailcp/article/details/89384328

https://www.cnblogs.com/lucas27/p/9292058.html

https://www.jianshu.com/p/c1a4166d9eda

https://blog.csdn.net/Leonardo_Zhu/article/details/96482371

https://www.jianshu.com/p/21f8ed30e761

目录
相关文章
|
2月前
|
前端开发 JavaScript 网络架构
react对antd中Select组件二次封装
本文介绍了如何在React中对Ant Design(antd)的Select组件进行二次封装,包括创建MSelect组件、定义默认属性、渲染Select组件,并展示了如何使用Less进行样式定义和如何在项目中使用封装后的Select组件。
81 2
react对antd中Select组件二次封装
|
13天前
|
前端开发 JavaScript
手敲Webpack 5:React + TypeScript项目脚手架搭建实践
手敲Webpack 5:React + TypeScript项目脚手架搭建实践
|
2月前
|
前端开发
React给antd中TreeSelect组件左侧加自定义图标icon
本文介绍了如何在React中为Ant Design的TreeSelect组件的每个树节点添加自定义图标,并解决了因缺少key属性而导致的警告问题,展示了如何通过递归函数处理treeData数据并为每个节点添加图标。
81 2
React给antd中TreeSelect组件左侧加自定义图标icon
|
2月前
|
前端开发
react使用antd中的Checkbox实现多选
在React项目中,通过Ant Design的Checkbox组件实现多选。引入Checkbox,使用Checkbox.Group来管理Checkbox,设置`value`属性绑定选中项数组,通过`onChange`更新数组。维护一个全选状态,根据选中项数量与总数决定全选按钮状态。全选按钮的`onChange`事件用于控制所有Checkbox的选中状态。
69 1
react使用antd中的Checkbox实现多选
|
2月前
|
前端开发
React添加路径别名alias、接受props默认值、并二次封装antd中Modal组件与使用
本文介绍了在React项目中如何添加路径别名alias以简化模块引入路径,设置组件props的默认值,以及如何二次封装Ant Design的Modal组件。文章还提供了具体的代码示例,包括配置Webpack的alias、设置defaultProps以及封装Modal组件的步骤和方法。
64 1
React添加路径别名alias、接受props默认值、并二次封装antd中Modal组件与使用
|
1月前
|
JavaScript 前端开发 安全
使用 TypeScript 加强 React 组件的类型安全
【10月更文挑战第1天】使用 TypeScript 加强 React 组件的类型安全
37 3
|
2月前
|
前端开发 JavaScript 区块链
react18函数组件+antd使用指南-使用代码集合以及报错记录汇总
本文介绍了多个React开发中常见的问题及其解决方案,包括但不限于:1)`useForm`实例未连接到任何`Form`元素的警告及解决方法;2)监听页面滚动事件的实现方式;3)React 18与antd 5.8.6中定制主题的方法;4)React结合antd 4.x版本自定义主题色的步骤;5)解决`ResizeObserver loop`相关报错的技巧;6)处理React设计表单时遇到的CDN资源加载失败问题;7)解决onClick事件传参问题;8)修复类型错误等。每部分均提供详细分析与实用代码示例,帮助开发者快速定位并解决问题。
39 2
|
2月前
|
前端开发 数据安全/隐私保护
react antd 实现修改密码(原密码,新密码,再次输入新密码,新密码增加正则复杂度校验)
文章介绍了如何在React项目中使用Ant Design实现一个修改密码的组件,包括原密码、新密码和再次输入新密码的表单项,并为新密码增加了正则表达式复杂度校验。
61 0
react antd 实现修改密码(原密码,新密码,再次输入新密码,新密码增加正则复杂度校验)
|
2月前
|
前端开发 计算机视觉
React使用antd实现可编辑单元格
React结合Ant Design实现可编辑单元格的表格组件,通过EditableRow和EditableCell封装实现单元格编辑功能,并提供saveFun回调保存编辑内容。
87 1
|
2月前
|
前端开发
React按需加载antd步骤以及出现的问题
在使用`babel-plugin-import`插件时,可以在项目的根目录创建`.babelrc`文件或在`package.json`中添加babel配置。这两个文件中不应该存在重复的配置。如果出现"Multiple configuration files found"错误,需要选择其中一个文件进行配置,并删除另一个文件中的babel配置。使用该插件后,可以直接从`antd`引入组件,无需手动引入样式文件。
60 1