一步一步创建dva项目,完成用户管理的 CURD 应用 (react+dva+antd)(填坑优化版)

前言

dva 官方项目里面有些用法不是最新的,本文针对性的解决并以正确的用法告知刚开始接触dva 项目的码友们 ,帮助大家避免入坑。
12 步 30 分钟,完成用户管理的 CURD 应用 优化版
git地址:https://github.com/Sawyer-china/react-user-dashboard
现在我们就开始一步一步的构建 如遇见问题可 添加 qq群:218618405 进行提问

如果你觉得该文章对你有帮助加个喜欢,github 加个 start 谢谢

1. 安装全局 dva-cli

$ npm install dva-cli -g

2. 创建项目

选好目录然后创建项目

$ dva new user-dashboard

3. 根据提示进入目录并运行项目

$ cd user-dashboard
$ npm start

如果看到以下页面,那么恭喜你,我们往下进行了


一步一步创建dva项目,完成用户管理的 CURD 应用 (react+dva+antd)(填坑优化版)_第1张图片
image.png

4. 引入antd组件库 (andt: 官方地址 https://ant.design/index-cn)

$ npm install antd --save

安装完成后打开 src/routes/IndexPage.js 引入一个antd组件试试 在文件头部引入

import Button from 'antd/lib/button'
import 'antd/lib/button/style/css';  

在function IndexPage 函数中使用组件


如果页面出现一个Button 则代表成功了

5. 按需加载

在项目中往往我们需要进行组件的按需加载以免去不必要的组件被打包到实际的项目中,以减少js的体积大小
安装以下插件

$ cnpm install babel-plugin-import --save-dev

并找到根目录下面的.webpackrc文件,并在文件中添加插件配置

"extraBabelPlugins": [
    ["import", { "libraryName": "antd", "style": "css" }]
]

配置更多玩法参考:https://github.com/sorrycc/roadhog/blob/master/README_zh-cn.md
修改以下代码

// import Button from 'antd/lib/button'
// import 'antd/lib/button/style/css'; 
import { Button } from 'antd'

6. 做 webpack 反向代理

在配置文件中添加以下代码

"proxy": {
        "/api": {
            "target": "http://jsonplaceholder.typicode.com/",
            "changeOrigin": true,
            "pathRewrite": { "^/api": "" }
        }
    }

访问 http://localhost:8000/api/users 如果你看见一串json数据代表代理成功,就可以进行下一步开发了(该json数据是dva官方提供的测试数据,使用Mockjs开发)
完成以上准备工作我们就开始正式的demo开发了

7. 创建 Users.js Router

在routes目录下创建Users.js

import React, { Component } from 'react'
import { connect } from 'dva'


import styles from './Users.css'

class Users extends Component {
    render() {
        return (
            
Users.js
) } } Users.propsTypes = {} export default connect()(Users)

8. 配置路由 打开根目录router.js

import React from 'react'
import { Router, Route, Switch, Redirect, routerRedux } from 'dva/router'
import IndexPage from './routes/IndexPage'

import dynamic from 'dva/dynamic' // 路由按需加载

const { ConnectedRouter } = routerRedux

function RouterConfig({ history, app }) {
    const IndexPage = dynamic({
        app,
        component: () => import('./routes/IndexPage')
    })
    const Users = dynamic({
        app,
        component: () => import('./routes/Users')
    })
    return (
        
                
                    
                    
                
        
    )
}

export default RouterConfig

浏览地址 输入 http://localhost:8000/#/users 将会看到 users 路由页面

9. 在components 文件夹下 新建 MainLayout/Header.js

import React, { Component } from 'react'
import { Menu, Icon } from 'antd'
import { connect } from 'dva'

import { Link, routerRedux } from 'dva/router'

class Header extends Component {
    render() {
        const { location } = this.props
        return (
            
                
                    
                        Users
                    
                
                
                    
                        Home
                    
                
                
                    
                        404
                    
                
                
                    dva
                
            
        )
    }
}

export default connect()(Header)

10. 在 components/MainLayout 新建MainLayout.js

import React, { Component } from 'react'
import styles from './MainLayout.css'
import Header from './Header'

class MainLayout extends Component {
    render() {
        const { children, location } = this.props
        return (
            
{children}
) } } export default MainLayout

11. 在 routes 中添加 App.js

import React, { Component } from 'react'
import { connect } from 'dva'
import { withRouter } from 'dva/router'

import MainLayout from '../components/MainLayout/MainLayout'


class App extends Component {
    render() {
        let { children, location } = this.props
        return (
            
                {children}
            
        )
    }
}

App.propTypes = {}

export default withRouter(
    connect(({ app, loading }) => ({
        app,
        loading
    }))(App)
)

添加完成之后修改 router.js 页面
在头部引入 App.js

import App from './routes/App'

然后修改return 中的代码

return (
        
            
                
                    
                    
                     } />
                
            
        
    )

现在就可以切换路由了如下图示:


一步一步创建dva项目,完成用户管理的 CURD 应用 (react+dva+antd)(填坑优化版)_第2张图片
222.gif

接下来着重users页面的开发

12. 创建 users model 和 service

新建 src/models/users.js:

// user api
import * as usersService from '../services/users'
// 引入 node 模块
// import url from 'url'
// import qs from 'qs'

export default {
   namespace: 'users',
   state: {
       list: [],
       total: 0,
       page: 0
   },
   reducers: {
       /**
        * test
        * @param {*} state 
        * @param {*} param1 
        */
       save(state, { payload: { data: list, total, page } }) {
           return { ...state, list, total, page }
       },
       search(state) {
           return { ...state }
       }
   },
   effects: {
       *fetch({ payload: { page } }, { call, put }) {
           const { data, headers } = yield call(usersService.fetch, { page })
           yield put({
               type: 'save',
               payload: {
                   data,
                   total: headers['x-total-count'],
                   page: parseInt(page, 10)
               }
           })
       },
       *create({ payload: values }, { call, put }) {
           yield call(usersService.create, values)
       },
       *patch({ payload: { id, values } }, { call, put }) {
           yield call(usersService.patch, { id, values })
           yield put({ type: 'reload' })
       },
       *remove({ payload: { id } }, { call, put }) {
           yield call(usersService.remove, { id })
           yield put({ type: 'reload' })
       },
       *reload(action, { put, select }) {
           const page = yield select(state => state.users.page)
           yield put({ type: 'fetch', payload: { page } })
       }
   },
   subscriptions: {
       // setup({ dispatch }, done) {
       //     done('错了错了')
       // throw new Error('Whoops!')
       // }
       setup({ dispatch, history }) {
           return history.listen(({ pathname, search }) => {
               // const { query } = url.parse(search)
               // const oPath = qs.parse(query)
               // if (pathname === '/users') {
               //     console.log('/users')
               //     console.log(oPath)
               //     dispatch({ type: 'fetch', payload: oPath })
               // }
           })
       }
   }
}

新建 src/services/users.js

import request from '../utils/request'

export function queryUsers() {
    return request('/api/users')
}

export function fetch({ page = 1 }) {
    return request(`/api/users?_page=${page}&_limit=5`)
}

export function create(values) {
    return request('/api/users', {
        methods: 'POST',
        data: JSON.stringify(values)
    })
}

export function patch({ id, values }) {
    return request(`/api/users/${id}`, {
        methods: 'PATCH',
        data: JSON.stringify(values)
    })
}

export function remove({ id }) {
    return request(`/api/users/${id}`, {
        methods: 'DELETE'
    })
}

由于我们需要从 response headers 中获取 total users 数量,所以需要改造下 src/utils/request.js:

import fetch from 'dva/fetch'

// function parseJSON(response) {
//     return response.json()
// }

function checkStatus(response) {
    if (response.status >= 200 && response.status < 300) {
        return response
    }

    const error = new Error(response.statusText)
    error.response = response
    throw error
}

/**
 * Requests a URL, returning a promise.
 *
 * @param  {string} url       The URL we want to request
 * @param  {object} [options] The options we want to pass to "fetch"
 * @return {object}           An object containing either "data" or "err"
 */
// export default function request(url, options) {
//   return fetch(url, options)
//     .then(checkStatus)
//     .then(parseJSON)
//     .then(data => ({ data }))
//     .catch(err => ({ err }));
// }

async function request(url, options) {
    const response = await fetch(url, options)
    checkStatus(response)
    const data = await response.json()
    const ret = {
        data,
        headers: {}
    }   

    if (response.headers.get('x-total-count')) {
        ret.headers['x-total-count'] = response.headers.get('x-total-count')
    }
    return ret
}

export default request

剩余部分请参考
https://github.com/sorrycc/blog/issues/18 (该代码可能有部分内容会导致错误)
请以一下链接为准
https://github.com/Sawyer-china/react-user-dashboard
最终完成效果如下图所示:

222.gif

如遇问题欢迎加群讨论
QQ群: 218618405
github:https://github.com/Sawyer-china

你可能感兴趣的:(一步一步创建dva项目,完成用户管理的 CURD 应用 (react+dva+antd)(填坑优化版))