umi入门

花时间学习了umi,算是对自己的学习总结,写了两个简单的demo:计数器和todoList。

1. 搭建项目

通过官网的介绍的脚手架搭建一个简单的项目,选择需要的功能的时候选择antd、dva后面会用到,完成后能在浏览器中 http://localhost:8000/ 看到项目。

2. 修改基础项目结构

  1. 在 src/pages 目录下新建2个文件夹:
  • count/index.jsx
export default function () {
  return (
    
count
) }
  • todoList/index.jsx
export default function () {
  return (
    
todoList
) }
  1. 修改 src/pages/index.js 实现首页到这两个新建页面的跳转
import styles from './index.css';
import Link from 'umi/link'

export default function () {
  return (
    
计数器
todoList
); }

现在在首页点击跳转回到404页面,这是因为还没有配置路由,路由配置在根目录下的 .umirc.js,

routes: [
    {
      path: '/',
      component: '../layouts/index',
      routes: [
        { path: '/', component: '../pages/index' }
      ]
    }
  ],

尝试使用umi的约定路由方式,umi 会根据 pages 目录自动生成路由配置,
将.umirc.js的routes配置注释,不注释会以配置文件中的路由配置为主
,现在路由就能正常跳转了。

3. 实现计数器功能

image

1. 实现简单的加、减

  1. 实现基本的页面结构,修改count/index.jsx
import { Button } from 'antd'
import styles from './index.css'

function Count() {
return (
  

数量:1

{' '}
) } export default Count
  1. 在count目录下新建model.js文件,用来进行状态数据的管理
export default {
  namespace: 'count',
  state: {
    count: 0
  },
  reducers: {
    increment(state) {
      return {
        count: state.count + 1
      }
    },
    decrement(state) {
      return {
        count: state.count - 1
      }
    }
  },
}
  1. 添加点击事件,实现数字的加、减

count/index.jsx

import { Button } from 'antd'
import styles from './index.css'
import { connect } from 'dva'

function Count({ count, increment, decrement }) {
  return (
    

数量:{count}

{' '}
) } const mapStateToProps = state => { return { count: state.count.count } } const mapDispatchToProps = dispatch => { return { increment: () => dispatch({ type: 'count/increment' }), decrement: () => dispatch({ type: 'count/decrement' }) } } export default connect(mapStateToProps, mapDispatchToProps)(Count)

完成上述操作,应该能实现简单的加、减功能了。

2. 实现带延迟的加、减

  1. 在count/model.js中添加异步操作的管理,实现延迟1s加、延迟2s减。
export default {
  ...
  effects: {
    *incrementAsync(actions, { put, call }) {
      yield call(delay, 1000)
      yield put({ type: 'increment' })
    },
    *decrementAsync(actions, { put, call }) {
      yield call(delay, 2000)
      yield put({ type: 'decrement' })
    }
  }
}

function delay(timeout) { // 延迟函数
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve()
    }, timeout)
  })
}
  1. 在 count/index.jsx 中添加异步操作
import { Button } from 'antd'
import styles from './index.css'
import { connect } from 'dva'

function Count({ count, increment, decrement, incrementAsync, decrementAsync }) {
  return (
    

数量:{count}

{' '}
{' '}
) } const mapStateToProps = state => { return { count: state.count.count } } const mapDispatchToProps = dispatch => { return { increment: () => dispatch({ type: 'count/increment' }), decrement: () => dispatch({ type: 'count/decrement' }), incrementAsync: () => dispatch({ type: 'count/incrementAsync' }), decrementAsync: () => dispatch({ type: 'count/decrementAsync' }) } } export default connect(mapStateToProps, mapDispatchToProps)(Count)

做完以上的步骤一个简单的计数器就基本完成了。

4. 实现一个todoList

image

1. 完成静态页面

  • 在 todoList 新建componets文件夹用来存放页面组件

components/AddTodo.jsx

import { Input, Button } from 'antd'
import styles from './addTodo.css'

function AddTodo() {

  return (
    
) } export default AddTodo

components/Todo.jsx

import { Typography, Button } from 'antd';
import styles from './todo.css'

const { Text } = Typography;

function Todo() {
  return (
    
123
) } export default Todo

todolist.jsx

import AddTodo from './components/AddTodo'
import Todo from './components/Todo'
import { List } from 'antd'
import styles from './index.css'

function TodoList() {

  return (
    
( )} />
) } export default TodoList

完成静态页面

image

2. 修改AddTodo组件,完成输入框输入,点击添加按钮显示输入的内容

函数组件没有生命周期和state,这里用到了react hook的usestate

import { Input, Button } from 'antd'
import styles from './addTodo.css'
import { useState } from 'react'

function AddTodo() {
  const [inputValue, setInputValue] = useState('')

  return (
    
{ setInputValue(e.target.value) }} />
) } export default AddTodo

在input中输入一段文字就能在控制台看到输入的内容了。

3. 新增models进行状态管理

  • todoList/models/todoList.js,新建初始state
export default {
  namespace: 'todoList',
  state: {
    list: [
      {
        content: '123',
        completed: false
      }
    ],
  }
}
  • 在todoList中展示state的内容
import AddTodo from './components/AddTodo'
import Todo from './components/Todo'
import { List } from 'antd'
import { connect } from 'dva'
import styles from './index.css'

function TodoList({ list }) {

  return (
    
( )} />
) } const mapStateToProps = state => { return { list: state.todoList.list } } export default connect(mapStateToProps)(TodoList)

修改Todo.js

import { Typography, Button } from 'antd';
import styles from './todo.css'

const { Text } = Typography;

function Todo({ completed, content }) {
  return (
    
{content}
) } export default Todo

4. 完成增、删、改的功能

  • 修改 models/todoList.js, 添加reducers
reducers: {
    addTodo(state, { payload: value }) { // 增
      return {
        list: [...state.list, { content: value, completed: false }]
      }
    },
    removeTodo(state, { payload: index }) { // 删
      let newList = state.list.filter((item, i) => i !== index)
      return {
        list: newList
      }
    },
    modifyTodo(state, { payload: index }) { // 改
      let newList = state.list.map((item, i) => {
        let flag = index === i ? !item.completed : item.completed
        return { ...item, completed: flag }
      })
      return {
        list: newList
      }
    }
  },
  • 修改AddTodo.jsx实现添加,将先前打印出的输入文字添加到list中来
import { Input, Button } from 'antd'
import styles from './addTodo.css'
import { useState } from 'react'
import { connect } from 'dva'

function AddTodo({ addTodo }) {
  const [inputValue, setInputValue] = useState('')

  return (
    
{ setInputValue(e.target.value) }} />
) } const mapDispatchToProps = dispatch => { return { addTodo: value => dispatch({ type: 'todoList/addTodo', payload: value }) } } export default connect(null, mapDispatchToProps)(AddTodo)
  • 修改 Todo.jsx,实现删除和修改
import { Typography, Button } from 'antd';
import styles from './todo.css'
import { connect } from 'dva'

const { Text } = Typography;

function Todo({ completed, content, index, removeTodo, modifyTodo }) {
  return (
    
{content}
) } const mapDispatchToProps = dispatch => { return { removeTodo: index => dispatch({ type: 'todoList/removeTodo', payload: index }), modifyTodo: index => dispatch({ type: 'todoList/modifyTodo', payload: index }) } } export default connect(null, mapDispatchToProps)(Todo)
  • 在 todoList/index.jsx中Todo添加index
  (
          
            
          
        )}
      />

5. 使用后台数据替换本地list的数据

使用umi-request来向后台发送请求,后台使用easy-mock进行数据模拟

  • 安装umi-request
yarn add umi-request
  • 请求放在models/todoList中处理
effects: {
    *getListAsync(actions, { put, call }) {
      const res = yield call(request, 'http://localhost:7300/mock/5dd4fcaebe523217231cce587/react-api/getList')
      yield put({ type: 'getList', payload: res.data.list })
    }
  }
  • 修改 todoList/index.jsx, 这里用到了useEffect
import { useEffect } from 'react'

function TodoList({ list, getList }) {
  useEffect(() => {
    getList()
  }, [getList])
  
......

const mapDisPatchToProps = dispacth => {
  return {
    getList: () => dispacth({ type: 'todoList/getListAsync' })
  }
}

export default connect(mapStateToProps, mapDisPatchToProps)(TodoList)

至此,两个简单的demo基本实现。

你可能感兴趣的:(umi入门)