Web前端之路程序员首页投稿(暂停使用,暂停投稿)

dva 从入门到入土

2017-09-29  本文已影响1568人  angeChen

dva 是对 redux 的一层浅封装,基于 react 语言,实现前端代码的分层

一般会分为3层:

以 smart-ui 项目中用户列表模块为例:


smart-ui

1. router.js 文件中配置路由,指定具体路径所要加载的 views 和 models

{
    path: '/security/users',
    models: () => [import('./models/security/user')],
    component: () => import('./views/security/user/'),
}

2. services

.roadhogrc.js文件中配置好代理请求地址

proxy: {
    "/api/v1/weather": {
      "target": "https://api.seniverse.com/",
      "changeOrigin": true,
      "pathRewrite": { "^/api/v1/weather" : "/v3/weather" }
    },
    "/services": {
        "target": "http://ip地址:8080/",
        "changeOrigin": true,
        "pathRewrite": { "^/services" : "/services" }
      },
  },

serviecs/user.js中定义好接口,获取原始数据。项目中,已对常用的增删改查做了一层封装(包括分页).
对于自定义方法,提供 url、method、data(可选),返回 request 封装好的 http 请求

export async function query({page = 1 , pageSize = 10 , ...qs}) {
    return user.listPage(page,pageSize,qs)
}

export async function get({id}) {
    return user.get(id)
}

export async function create (params) {
    return user.create(params);
}

export async function update (params) {
    return user.update(params);
}

// 用户设置 自定义方法
//修改用户
export async function modify(payload) {
    return request({
        url: `${apiPrefix}/security/user/modify`,
        method: 'put',
        data: payload
    })
}

3. models

import pathToRegexp from 'path-to-regexp'
import modelExtend from 'dva-model-extend'
import * as user from 'services/security/user'
import { pageModel } from 'models/common'
import { message } from 'antd'

export default modelExtend(pageModel, {

  namespace: 'secUser',

  state: {
   currentItem: {},
   modalVisible: false,
   modalType: 'create',
   selectedRowKeys: [],
  },
  
  // 添加一个监听器,当pathname === '/security/users'时执行dispatch
  subscriptions: {
    setup ({ dispatch, history }) {
      history.listen((location) => {
        if (location.pathname === '/security/users') {
          dispatch({ 
              type: 'query', 
              payload: location.query || {},
          })
        }
      })
    },
  },

// 
  effects: {
    * query ({
      payload,
    }, { call, put }) {
      const result = yield call(user.query, payload)
      const { success, message, status, data } = result
      if (success) {
        yield put({
          type: 'querySuccess',
          payload: data,
        })
      } else {
        throw result
      }
    },

    * create ({ payload }, { call, put,select }) {
      const {data} = yield call(user.create, payload)
      message.info("新增成功");   
      yield put({ type: 'hideModal' })
      const { pagination: { pageSize,current } } = yield select(_ => _.secUser)
      yield put({ type: 'query', payload: {pageSize, page:current } })
    },

    * update ({ payload }, { select, call, put }) {
      const id = yield select(({ secUser }) => secUser.currentItem.id)
      const newUser = { ...payload, id }
      const {data} = yield call(user.update, newUser)
      message.info("修改成功");
      yield put({ type: 'hideModal' })
      const { pagination: { pageSize,current } } = yield select(_ => _.secUser)
      yield put({ type: 'query', payload: {pageSize, page:current } })
    },
  },

  reducers: {
     showModal (state, { payload }) {
      return { ...state, ...payload, modalVisible: true }
    },

    hideModal (state) {
      return { ...state, modalVisible: false }
    },
  },
})

4.component

注意:组件入口文件一定要命名为 index.js ,否则会找不到

import React from 'react'
import PropTypes from 'prop-types'
import { routerRedux } from 'dva/router'
import { connect } from 'dva'
import { Row, Col, Button, Popconfirm } from 'antd'
import List from './List'
import Filter from './Filter'
import Modal from './Modal'
import { Page } from 'components'
import { i18n }  from 'utils'

const User = ({ location, dispatch, secUser, loading }) => {
  const { dataSource, pagination, currentItem, modalVisible, modalType, selectedRowKeys } = secUser
  const { pageSize } = 10

  const modalProps = {
    item: modalType === 'create' ? {} : currentItem,
    visible: modalVisible,
    maskClosable: false,
    confirmLoading: loading.effects['secUser/update'],
    title: modalType === 'create' ? i18n('lab.user.create') : i18n('lab.user.update'),
    wrapClassName: 'vertical-center-modal',
    onOk (data) {
      dispatch({
        type: `secUser/${modalType}`,
        payload: data,
      })
    },
    onCancel () {
      dispatch({
        type: 'secUser/hideModal',
      })
    },
  }

  const listProps = {
    dataSource,
    loading: loading.effects['secUser/query'],
    pagination,
    location,
    onChange (page) {
      const { query, pathname } = location
      dispatch(routerRedux.push({
        pathname,
        query: {
          ...query,
          page: page.current,
          pageSize: page.pageSize,
        },
      }))
    },
    onDeleteItem (id) {
      dispatch({
        type: 'secUser/delete',
        payload: id,
      })
    },
    onEditItem (item) {
      dispatch({
        type: 'secUser/showModal',
        payload: {
          modalType: 'update',
          currentItem: item,
        },
      })
    },
    rowSelection: {
      selectedRowKeys,
      onChange: (keys) => {
        dispatch({
          type: 'secUser/updateState',
          payload: {
            selectedRowKeys: keys,
          },
        })
      },
    },
  }

  const filterProps = {
    ...
  }

  const handleDeleteItems = () => {
    dispatch({
      type: 'secUser/multiDelete',
      payload: {
        ids: selectedRowKeys,
      },
    })
  }

  return (
    <Page inner>
      <Filter {...filterProps} />
      <List {...listProps} />
      {modalVisible && <Modal {...modalProps} />}
    </Page>
  )
}

User.propTypes = {
  secUser: PropTypes.object,
  location: PropTypes.object,
  dispatch: PropTypes.func,
  loading: PropTypes.object,
}

export default connect(({ secUser }) => ({ secUser}))(User)
上一篇下一篇

猜你喜欢

热点阅读