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

目录
相关文章
|
1月前
|
前端开发 JavaScript 安全
TypeScript在React Hooks中的应用:提升React开发的类型安全与可维护性
【7月更文挑战第17天】TypeScript在React Hooks中的应用极大地提升了React应用的类型安全性和可维护性。通过为状态、依赖项和自定义Hooks指定明确的类型,开发者可以编写更加健壮、易于理解和维护的代码。随着React和TypeScript的不断发展,结合两者的优势将成为构建现代Web应用的标准做法。
|
1月前
|
JavaScript 前端开发 IDE
React 项目中有效地使用 TypeScript
React 项目中有效地使用 TypeScript
|
1月前
|
前端开发 JavaScript 开发者
React 和 TypeScript
React 和 TypeScript
|
2月前
|
资源调度 前端开发
|
2月前
|
前端开发 JavaScript 开发者
React和TypeScript各自以其独特的优势赢得了广大开发者的青睐
【6月更文挑战第12天】React和TypeScript是前端开发的强强联合。TypeScript提供静态类型检查和面向对象特性,增强代码健壮性和团队协作效率;React凭借组件化、高性能和丰富生态系统引领UI构建。两者结合,能精确定义React组件类型,提升代码组织和维护性,通过安装TypeScript、配置、编写及构建步骤,可在React项目中实现这一优势。这种结合为前端开发带来进步,未来应用将更加广泛。
36 1
|
3月前
|
JavaScript 前端开发 开发者
【TypeScript技术专栏】TypeScript与React的完美结合
【4月更文挑战第30天】React和TypeScript在前端开发中备受推崇。React以其组件化、高性能和灵活的生态系统引领UI构建,而TypeScript通过静态类型检查和面向对象特性增强了代码的健壮性和可维护性。两者结合,能提升开发效率,降低错误,使React组件结构更清晰。通过安装TypeScript,配置tsconfig.json,然后用TypeScript编写和打包代码,可实现两者的无缝集成。这种结合为前端开发带来更强的代码质量和团队协作效果,随着技术发展,其应用将更加广泛。
44 0
|
3月前
|
前端开发 JavaScript 安全
【亮剑】探讨了在React TypeScript应用中如何通过道具(props)传递CSS样式,以实现模块化、主题化和动态样式
【4月更文挑战第30天】本文探讨了在React TypeScript应用中如何通过道具(props)传递CSS样式,以实现模块化、主题化和动态样式。文章分为三部分:首先解释了样式传递的必要性,包括模块化、主题化和动态样式以及TypeScript集成。接着介绍了内联样式的基本用法和最佳实践,展示了一个使用内联样式自定义按钮颜色的例子。最后,讨论了使用CSS模块和TypeScript接口处理复杂样式的方案,强调了它们在组织和重用样式方面的优势。结合TypeScript,确保了样式的正确性和可维护性,为开发者提供了灵活的样式管理策略。
46 0
|
3月前
|
前端开发 JavaScript 定位技术
Docusaurus框架——react+antd+echarts自定义mdx生成图表代码解释文档
Docusaurus框架——react+antd+echarts自定义mdx生成图表代码解释文档
83 0
|
7天前
|
JavaScript
TypeScript——不能将类型“HTMLElement | null”分配给类型“HTMLElement”
TypeScript——不能将类型“HTMLElement | null”分配给类型“HTMLElement”
19 4
|
12天前
|
JavaScript 编译器
typescript 解决变量多类型访问属性报错--工作随记
typescript 解决变量多类型访问属性报错--工作随记