├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .gitignore ├── README.md ├── mock └── example.js ├── package.json ├── proxy.config.js ├── src ├── assets │ └── yay.jpg ├── components │ ├── Example.js │ ├── Silder.js │ └── breadcrumb.js ├── config │ └── config.js ├── index.css ├── index.html ├── index.js ├── models │ ├── 11.js │ ├── common.js │ └── example.js ├── router.js ├── routes │ ├── 1-1.js │ ├── 1-2.js │ ├── 2-1.js │ ├── 2-2.js │ ├── 3-1.js │ ├── 3-2.js │ ├── 3-3.js │ ├── 3-4.js │ ├── IndexPage.css │ └── IndexPage.js ├── services │ └── example.js ├── tests │ └── models │ │ └── example-test.js └── utils │ ├── query.js │ └── request.js └── webpack.config.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | 15 | [Makefile] 16 | indent_style = tab 17 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | src/**/*-test.js 2 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "extends": "eslint-config-airbnb", 4 | "rules": { 5 | "spaced-comment": [0], 6 | "no-unused-vars": [0], 7 | "no-empty": [0], 8 | "react/wrap-multilines": [0], 9 | "react/no-multi-comp": [0], 10 | "no-constant-condition": [0], 11 | "react/jsx-no-bind": [0], 12 | "react/prop-types": [0], 13 | "arrow-body-style": [0], 14 | "react/prefer-stateless-function": [0], 15 | "semi": [0], 16 | "global-require": [0], 17 | "no-shadow": [0], 18 | "no-useless-computed-key": [0], 19 | "no-underscore-dangle": [0] 20 | }, 21 | "ecmaFeatures": { 22 | "experimentalObjectRestSpread": true 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 这是一个基于dva的基础小项目,主要是配合自己的博客文章,作为示范demo使用。 2 | 3 | [基于dva-cli&antd的react项目实战](http://que01.top/2016/11/20/dva-react/) 4 | -------------------------------------------------------------------------------- /mock/example.js: -------------------------------------------------------------------------------- 1 | var co = require('co'); 2 | var fetch = require('node-fetch'); 3 | var safeeval = require('safe-eval'); 4 | var mockjs = require('mockjs'); 5 | var Host = 'http://rap.taobao.org/mockjs/5889' 6 | 7 | function mockMapFun(req,res){ 8 | co(function *() { 9 | var response = yield fetch(Host + req.url); 10 | var mockTpl = yield response.text(); 11 | res.json( mockjs.mock(safeeval(mockTpl))['data'] ); 12 | }); 13 | } 14 | 15 | module.exports = { 16 | 'GET /member/list': mockMapFun 17 | }; 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "entry": { 4 | "index": "./src/index.js", 5 | "common": [ 6 | "react" 7 | ] 8 | }, 9 | "dependencies": { 10 | "antd": "^2.4.3", 11 | "dva": "^1.1.0", 12 | "html-webpack-plugin": "^2.24.1", 13 | "html-webpack-template": "^5.4.1", 14 | "merge-object": "^1.0.0", 15 | "mockjs": "^1.0.1-beta3", 16 | "object-to-formdata": "^1.0.7", 17 | "qs": "^6.3.0", 18 | "react": "^15.3.2", 19 | "react-dom": "^15.3.2", 20 | "safe-eval": "^0.3.0" 21 | }, 22 | "devDependencies": { 23 | "atool-build": "^0.9.0", 24 | "atool-test-mocha": "^0.1.5", 25 | "babel-plugin-dev-expression": "^0.2.1", 26 | "babel-plugin-dva-hmr": "^0.2.0", 27 | "babel-plugin-import": "^1.1.0", 28 | "babel-plugin-transform-runtime": "^6.9.0", 29 | "babel-runtime": "^6.9.2", 30 | "co": "^4.6.0", 31 | "dora": "^0.4.3", 32 | "dora-plugin-proxy": "^0.8.4", 33 | "dora-plugin-webpack": "^0.8.1", 34 | "dora-plugin-webpack-hmr": "^0.2.1", 35 | "expect": "^1.20.2", 36 | "node-fetch": "^1.6.3", 37 | "redbox-react": "^1.3.2" 38 | }, 39 | "scripts": { 40 | "start": "dora --plugins \"proxy?watchDirs=./mock,webpack,webpack-hmr\"", 41 | "build": "atool-build --hash", 42 | "test": "atool-test-mocha ./src/**/*-test.js" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /proxy.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const mock = {}; 4 | 5 | require('fs').readdirSync(require('path').join(__dirname + '/mock')) 6 | .forEach(function (file) { 7 | Object.assign(mock, require('./mock/' + file)); 8 | }); 9 | 10 | module.exports = mock; 11 | -------------------------------------------------------------------------------- /src/assets/yay.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/que01/dva-demo/bb1d0f1ba62d378ee12e0169bd7f83accadbfb78/src/assets/yay.jpg -------------------------------------------------------------------------------- /src/components/Example.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const Example = (props) => { 4 | return ( 5 |
6 | Example 7 |
8 | ); 9 | }; 10 | 11 | Example.propTypes = { 12 | }; 13 | 14 | export default Example; 15 | -------------------------------------------------------------------------------- /src/components/Silder.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Menu, Icon } from 'antd'; 3 | import { Link } from 'dva/router' 4 | const SubMenu = Menu.SubMenu; 5 | const MenuItemGroup = Menu.ItemGroup; 6 | 7 | const Sider = React.createClass({ 8 | getInitialState() { 9 | return { 10 | current: '1', 11 | }; 12 | }, 13 | handleClick(e) { 14 | console.log('click ', e); 15 | this.setState({ 16 | current: e.key, 17 | }); 18 | }, 19 | render() { 20 | return ( 21 | 27 | 菜单一}> 28 | 菜单一1 29 | 菜单一2 30 | 31 | 菜单二}> 32 | 菜单二1 33 | 菜单二2 34 | 35 | 菜单三}> 36 | 菜单三1 37 | 菜单三2 38 | 菜单三3 39 | 菜单三4 40 | 41 | 42 | ); 43 | }, 44 | }); 45 | 46 | export default Sider 47 | -------------------------------------------------------------------------------- /src/components/breadcrumb.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Breadcrumb } from 'antd'; 3 | import { Link } from 'dva/router' 4 | const breadcrumb = (props)=>{ 5 | return ( 6 | 7 | { 8 | props.data.map((v,i)=>( 9 | 10 | {v.path?({v.name}):v.name} 11 | 12 | )) 13 | } 14 | 15 | ) 16 | }; 17 | export default breadcrumb; 18 | -------------------------------------------------------------------------------- /src/config/config.js: -------------------------------------------------------------------------------- 1 | const config = { 2 | rapHost:'http://rap.taobao.org/mockjs/5889', 3 | rapFlag:true, 4 | onlinePath:'/api/' 5 | } 6 | export default config 7 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | 2 | :global { 3 | html, body, #root { 4 | height: 100%; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Dva Demo 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import './index.html'; 2 | import './index.css'; 3 | import dva from 'dva'; 4 | 5 | // 1. Initialize 6 | const app = dva(); 7 | 8 | app.model(require("./models/common")); 9 | 10 | app.model(require("./models/11")); 11 | 12 | // 2. Plugins 13 | //app.use({}); 14 | 15 | // 3. Model 16 | //app.model(require('./models/example')); 17 | 18 | // 4. Router 19 | app.router(require('./router')); 20 | 21 | // 5. Start 22 | app.start('#root'); 23 | -------------------------------------------------------------------------------- /src/models/11.js: -------------------------------------------------------------------------------- 1 | import { GET } from '../utils/query' 2 | import { rapFlag, onlinePath } from '../config/config'; 3 | const API = 'member/list' 4 | export default { 5 | namespace: 'test', 6 | state: { 7 | list:{ 8 | data:[], 9 | loading:true, 10 | }, 11 | pagination:{ 12 | current:1, 13 | pageSize:10, 14 | total:null 15 | } 16 | }, 17 | reducers: { 18 | fetchList(state, action) { 19 | return { ...state, ...action.payload }; 20 | }, 21 | }, 22 | effects: { 23 | *fetchRemote({ payload }, { call, put }) { 24 | let {current,pageSize} = payload; 25 | let { data } = yield call(GET,API,{ 26 | pageNum:current, 27 | pageSize:pageSize, 28 | }); 29 | if (data) { 30 | yield put({ 31 | type: 'fetchList', 32 | payload: { 33 | list: { 34 | data:data.results, 35 | loading:false 36 | }, 37 | pagination: data.info 38 | } 39 | }); 40 | } 41 | }, 42 | }, 43 | subscriptions: {}, 44 | } 45 | -------------------------------------------------------------------------------- /src/models/common.js: -------------------------------------------------------------------------------- 1 | export default { 2 | namespace: 'common', 3 | state: { 4 | breadcrumb:[ 5 | { 6 | name:'首页', 7 | path:'/dashboard' 8 | } 9 | ] 10 | }, 11 | reducers: { 12 | changeBreadcrumb(state,{ payload: breadcrumb }) { 13 | return {...state, ...breadcrumb} 14 | } 15 | }, 16 | effects: {}, 17 | subscriptions: {}, 18 | } 19 | -------------------------------------------------------------------------------- /src/models/example.js: -------------------------------------------------------------------------------- 1 | 2 | export default { 3 | 4 | namespace: 'example', 5 | 6 | state: {}, 7 | 8 | subscriptions: { 9 | setup({ dispatch, history }) { 10 | }, 11 | }, 12 | 13 | effects: { 14 | *fetchRemote({ payload }, { call, put }) { 15 | }, 16 | }, 17 | 18 | reducers: { 19 | fetch(state, action) { 20 | return { ...state, ...action.payload }; 21 | }, 22 | }, 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/router.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import { Router, Route, IndexRoute, Link } from 'dva/router'; 3 | import IndexPage from './routes/IndexPage'; 4 | 5 | const r11 = (location, callback) => { 6 | require.ensure([], require => {callback(null, 7 | require('./routes/1-1'))}, '11') 8 | }; 9 | const r12 = (location, callback) => { 10 | require.ensure([], require => {callback(null, 11 | require('./routes/1-2'))}, '12') 12 | }; 13 | const r21 = (location, callback) => { 14 | require.ensure([], require => {callback(null, 15 | require('./routes/2-1'))}, '21') 16 | }; 17 | const r22 = (location, callback) => { 18 | require.ensure([], require => {callback(null, 19 | require('./routes/2-2'))}, '22') 20 | }; 21 | const r31 = (location, callback) => { 22 | require.ensure([], require => {callback(null, 23 | require('./routes/3-1'))}, '31') 24 | }; 25 | const r32 = (location, callback) => { 26 | require.ensure([], require => {callback(null, 27 | require('./routes/3-2'))}, '32') 28 | }; 29 | const r33 = (location, callback) => { 30 | require.ensure([], require => {callback(null, 31 | require('./routes/3-3'))}, '33') 32 | }; 33 | const r34 = (location, callback) => { 34 | require.ensure([], require => {callback(null, 35 | require('./routes/3-4'))}, '34') 36 | }; 37 | 38 | export default function({ history }) { 39 | return ( 40 | 41 | 42 | {/* 添加一个路由,嵌套进我们想要嵌套的 UI 里 */} 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | ); 54 | }; 55 | -------------------------------------------------------------------------------- /src/routes/1-1.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'dva'; 3 | import {Table,Icon} from 'antd'; 4 | 5 | const columns = [ 6 | { 7 | title: 'Name', 8 | dataIndex: 'name', 9 | key: 'name', 10 | render: text => {text}, 11 | }, { 12 | title: 'Age', 13 | dataIndex: 'age', 14 | key: 'age', 15 | }, { 16 | title: 'Address', 17 | dataIndex: 'address', 18 | key: 'address', 19 | }, { 20 | title: 'LastLogin', 21 | dataIndex: 'lastLogin', 22 | key: 'lastLogin', 23 | } 24 | ]; 25 | 26 | 27 | class Option extends React.Component{ 28 | constructor(props){ 29 | super(props) 30 | } 31 | render(){ 32 | let {data,loading} = this.props.test.list; 33 | let pagination = this.props.test.pagination; 34 | return ( 35 | 42 | ) 43 | } 44 | handleTableChange(pagination, filters, sorter){ 45 | this.props.dispatch({ 46 | type:'test/changePage', 47 | payload:{ 48 | pagination:{ 49 | current:pagination.current, 50 | pageSize:pagination.pageSize, 51 | showQuickJumper: true, 52 | loading:true 53 | } 54 | } 55 | }); 56 | this.fetch(pagination.current) 57 | } 58 | fetch(current){ 59 | // 更新列表 60 | this.props.dispatch({ 61 | type:'test/fetchRemote', 62 | payload:{ 63 | current:current, 64 | pageSize:10, 65 | loading:false, 66 | } 67 | }); 68 | } 69 | componentDidMount(){ 70 | const breadcrumbData = { 71 | breadcrumb:[ 72 | { 73 | name:'首页', 74 | path:'/' 75 | },{ 76 | name:'菜单一1' 77 | } 78 | ] 79 | }; 80 | this.props.dispatch({ 81 | type:'common/changeBreadcrumb', 82 | payload:breadcrumbData 83 | }); 84 | this.fetch(1); 85 | } 86 | } 87 | function mapStateToProps({ common,test }) { 88 | return {common,test}; 89 | } 90 | export default connect(mapStateToProps)(Option); 91 | -------------------------------------------------------------------------------- /src/routes/1-2.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'dva'; 3 | class Option extends React.Component{ 4 | constructor(props){ 5 | super(props) 6 | } 7 | render(){ 8 | return (
菜单一2
) 9 | } 10 | componentDidMount(){ 11 | const breadcrumbData = { 12 | breadcrumb:[ 13 | { 14 | name:'首页', 15 | path:'/' 16 | },{ 17 | name:'菜单一2' 18 | } 19 | ] 20 | }; 21 | this.props.dispatch({ 22 | type:'common/changeBreadcrumb', 23 | payload:breadcrumbData 24 | }) 25 | } 26 | } 27 | function mapStateToProps({ common }) { 28 | return {common}; 29 | } 30 | export default connect(mapStateToProps)(Option); 31 | -------------------------------------------------------------------------------- /src/routes/2-1.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'dva'; 3 | class Option extends React.Component{ 4 | constructor(props){ 5 | super(props) 6 | } 7 | render(){ 8 | return (
菜单二1
) 9 | } 10 | componentDidMount(){ 11 | const breadcrumbData = { 12 | breadcrumb:[ 13 | { 14 | name:'首页', 15 | path:'/' 16 | },{ 17 | name:'菜单二1' 18 | } 19 | ] 20 | }; 21 | this.props.dispatch({ 22 | type:'common/changeBreadcrumb', 23 | payload:breadcrumbData 24 | }) 25 | } 26 | } 27 | function mapStateToProps({ common }) { 28 | return {common}; 29 | } 30 | export default connect(mapStateToProps)(Option); 31 | -------------------------------------------------------------------------------- /src/routes/2-2.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'dva'; 3 | class Option extends React.Component{ 4 | constructor(props){ 5 | super(props) 6 | } 7 | render(){ 8 | return (
菜单二2
) 9 | } 10 | componentDidMount(){ 11 | const breadcrumbData = { 12 | breadcrumb:[ 13 | { 14 | name:'首页', 15 | path:'/' 16 | },{ 17 | name:'菜单二2' 18 | } 19 | ] 20 | }; 21 | this.props.dispatch({ 22 | type:'common/changeBreadcrumb', 23 | payload:breadcrumbData 24 | }) 25 | } 26 | } 27 | function mapStateToProps({ common }) { 28 | return {common}; 29 | } 30 | export default connect(mapStateToProps)(Option); 31 | -------------------------------------------------------------------------------- /src/routes/3-1.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'dva'; 3 | class Option extends React.Component{ 4 | constructor(props){ 5 | super(props) 6 | } 7 | render(){ 8 | return (
菜单三1
) 9 | } 10 | componentDidMount(){ 11 | const breadcrumbData = { 12 | breadcrumb:[ 13 | { 14 | name:'首页', 15 | path:'/' 16 | },{ 17 | name:'菜单三1' 18 | } 19 | ] 20 | }; 21 | this.props.dispatch({ 22 | type:'common/changeBreadcrumb', 23 | payload:breadcrumbData 24 | }) 25 | } 26 | } 27 | function mapStateToProps({ common }) { 28 | return {common}; 29 | } 30 | export default connect(mapStateToProps)(Option); 31 | -------------------------------------------------------------------------------- /src/routes/3-2.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'dva'; 3 | class Option extends React.Component{ 4 | constructor(props){ 5 | super(props) 6 | } 7 | render(){ 8 | return (
菜单三2
) 9 | } 10 | componentDidMount(){ 11 | const breadcrumbData = { 12 | breadcrumb:[ 13 | { 14 | name:'首页', 15 | path:'/' 16 | },{ 17 | name:'菜单三2' 18 | } 19 | ] 20 | }; 21 | this.props.dispatch({ 22 | type:'common/changeBreadcrumb', 23 | payload:breadcrumbData 24 | }) 25 | } 26 | } 27 | function mapStateToProps({ common }) { 28 | return {common}; 29 | } 30 | export default connect(mapStateToProps)(Option); 31 | -------------------------------------------------------------------------------- /src/routes/3-3.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'dva'; 3 | class Option extends React.Component{ 4 | constructor(props){ 5 | super(props) 6 | } 7 | render(){ 8 | return (
菜单三3
) 9 | } 10 | componentDidMount(){ 11 | const breadcrumbData = { 12 | breadcrumb:[ 13 | { 14 | name:'首页', 15 | path:'/' 16 | },{ 17 | name:'菜单三3' 18 | } 19 | ] 20 | }; 21 | this.props.dispatch({ 22 | type:'common/changeBreadcrumb', 23 | payload:breadcrumbData 24 | }) 25 | } 26 | } 27 | function mapStateToProps({ common }) { 28 | return {common}; 29 | } 30 | export default connect(mapStateToProps)(Option); 31 | -------------------------------------------------------------------------------- /src/routes/3-4.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'dva'; 3 | class Option extends React.Component{ 4 | constructor(props){ 5 | super(props) 6 | } 7 | render(){ 8 | return (
菜单三4
) 9 | } 10 | componentDidMount(){ 11 | const breadcrumbData = { 12 | breadcrumb:[ 13 | { 14 | name:'首页', 15 | path:'/' 16 | },{ 17 | name:'菜单三4' 18 | } 19 | ] 20 | }; 21 | this.props.dispatch({ 22 | type:'common/changeBreadcrumb', 23 | payload:breadcrumbData 24 | }) 25 | } 26 | } 27 | function mapStateToProps({ common }) { 28 | return {common}; 29 | } 30 | export default connect(mapStateToProps)(Option); 31 | -------------------------------------------------------------------------------- /src/routes/IndexPage.css: -------------------------------------------------------------------------------- 1 | 2 | .normal { 3 | font-family: Georgia, sans-serif; 4 | margin-top: 3em; 5 | text-align: center; 6 | } 7 | 8 | .title { 9 | font-size: 2.5rem; 10 | font-weight: normal; 11 | letter-spacing: -1px; 12 | } 13 | 14 | .welcome { 15 | height: 328px; 16 | background: url(../assets/yay.jpg) no-repeat center 0; 17 | background-size: 388px 328px; 18 | } 19 | 20 | .list { 21 | font-size: 1.2em; 22 | margin-top: 1.8em; 23 | list-style: none; 24 | line-height: 1.5em; 25 | } 26 | 27 | .list code { 28 | background: #f7f7f7; 29 | } 30 | -------------------------------------------------------------------------------- /src/routes/IndexPage.js: -------------------------------------------------------------------------------- 1 | import React, { Component, PropTypes } from 'react'; 2 | import { connect } from 'dva'; 3 | import { Link } from 'dva/router'; 4 | import styles from './IndexPage.css'; 5 | 6 | import Silder from '../components/Silder' 7 | import CustomBreadcrumb from '../components/breadcrumb' 8 | 9 | import { Row, Col } from 'antd'; 10 | 11 | const breadcrumbData = [ 12 | { 13 | name:'首页', 14 | path:'/' 15 | },{ 16 | name:'菜单21', 17 | path:'/21' 18 | } 19 | ]; 20 | 21 | class App extends Component { 22 | constructor(props){ 23 | super(props) 24 | } 25 | render(){ 26 | return( 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | {this.props.children||'内容区域'} 36 | 37 | 38 | ) 39 | } 40 | } 41 | 42 | function mapStateToProps({ common }) { 43 | return {common}; 44 | } 45 | export default connect(mapStateToProps)(App); 46 | -------------------------------------------------------------------------------- /src/services/example.js: -------------------------------------------------------------------------------- 1 | import request from '../utils/request'; 2 | 3 | export async function query() { 4 | return request('/api/users'); 5 | } 6 | -------------------------------------------------------------------------------- /src/tests/models/example-test.js: -------------------------------------------------------------------------------- 1 | import expect from 'expect'; 2 | import example from '../../models/example'; 3 | 4 | describe('example', () => { 5 | 6 | describe('reducer', () => { 7 | it('it should save', () => { 8 | expect(example.reducers['example/save']({}, { payload: { a: 1 }})).toEqual({ a: 1 }); 9 | }); 10 | }) 11 | }); 12 | -------------------------------------------------------------------------------- /src/utils/query.js: -------------------------------------------------------------------------------- 1 | import request from '../utils/request'; 2 | import qs ,{ parse } from 'qs'; 3 | import FormdataWrapper from 'object-to-formdata'; 4 | import merge from 'merge-object'; 5 | import {rapHost, onlinePath} from '../config/config' 6 | 7 | const cookieTrue = { 8 | credentials: 'include' 9 | }; 10 | const jsonConf = { 11 | headers: { 12 | 'Content-Type': 'application/json' 13 | } 14 | } 15 | 16 | function getUrl(smarturl,flag) { 17 | if(flag){ 18 | return rapHost + '/' + smarturl; 19 | }else{ 20 | return onlinePath + smarturl; 21 | } 22 | } 23 | 24 | async function POST(url,params,isJson){ 25 | if(isJson == undefined){isJson = false}; 26 | return request( url,merge({ 27 | method: 'POST', 28 | body:isJson?JSON.stringify(params):FormdataWrapper(params), 29 | },isJson?merge(jsonConf,cookieTrue):cookieTrue),rapFlag); 30 | } 31 | 32 | async function GET(url,params){ 33 | return request( url + `?${qs.stringify(params)}`,merge({ 34 | method: 'GET', 35 | },cookieTrue)); 36 | } 37 | 38 | export { 39 | POST,GET 40 | } 41 | -------------------------------------------------------------------------------- /src/utils/request.js: -------------------------------------------------------------------------------- 1 | import fetch from 'dva/fetch'; 2 | import safeeval from 'safe-eval' 3 | import Mock from 'mockjs'; 4 | 5 | function parseText(response) { 6 | return response.json(); 7 | } 8 | 9 | function checkStatus(response) { 10 | if (response.status >= 200 && response.status < 300) { 11 | return response; 12 | } 13 | const error = new Error(response.statusText); 14 | error.response = response; 15 | throw error; 16 | } 17 | 18 | /** 19 | * Requests a URL, returning a promise. 20 | * 21 | * @param {string} url The URL we want to request 22 | * @param {object} [options] The options we want to pass to "fetch" 23 | * @return {object} An object containing either "data" or "err" 24 | */ 25 | export default function request(url, options) { 26 | return fetch(url, options) 27 | .then(checkStatus) 28 | .then(parseText) 29 | .then((data) => ({ data })) 30 | .catch((err) => ({ err })); 31 | } 32 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('atool-build/lib/webpack'); 2 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | 4 | module.exports = function(webpackConfig, env) { 5 | webpackConfig.babel.plugins.push('transform-runtime'); 6 | 7 | // Support hmr 8 | if (env === 'development') { 9 | webpackConfig.devtool = '#eval'; 10 | webpackConfig.babel.plugins.push('dva-hmr'); 11 | } else { 12 | webpackConfig.babel.plugins.push('dev-expression'); 13 | webpackConfig.plugins.push( 14 | new HtmlWebpackPlugin({ 15 | inject: false, 16 | template: require('html-webpack-template'), 17 | title: 'Dva Demo', 18 | appMountId: 'root', 19 | minify: { 20 | removeComments: true, 21 | collapseWhitespace: true 22 | }, 23 | links:['//at.alicdn.com/t/font_xxxxxxxx.css'] 24 | }) 25 | ); 26 | } 27 | 28 | // Don't extract common.js and common.css 29 | webpackConfig.plugins = webpackConfig.plugins.filter(function(plugin) { 30 | return !(plugin instanceof webpack.optimize.CommonsChunkPlugin); 31 | }); 32 | 33 | // Support CSS Modules 34 | // Parse all less files as css module. 35 | webpackConfig.module.loaders.forEach(function(loader, index) { 36 | if (typeof loader.test === 'function' && loader.test.toString().indexOf('\\.less$') > -1) { 37 | loader.include = /node_modules/; 38 | loader.test = /\.less$/; 39 | } 40 | if (loader.test.toString() === '/\\.module\\.less$/') { 41 | loader.exclude = /node_modules/; 42 | loader.test = /\.less$/; 43 | } 44 | if (typeof loader.test === 'function' && loader.test.toString().indexOf('\\.css$') > -1) { 45 | loader.include = /node_modules/; 46 | loader.test = /\.css$/; 47 | } 48 | if (loader.test.toString() === '/\\.module\\.css$/') { 49 | loader.exclude = /node_modules/; 50 | loader.test = /\.css$/; 51 | } 52 | }); 53 | 54 | webpackConfig.babel.plugins.push(['import', { 55 | libraryName: 'antd', 56 | style: 'css', 57 | }]); 58 | 59 | return webpackConfig; 60 | }; 61 | --------------------------------------------------------------------------------