diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..7e3649a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,16 @@ +# http://editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false + +[Makefile] +indent_style = tab diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..a72e2f7 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,32 @@ +{ + "parser": "babel-eslint", + "extends": "airbnb", + "rules": { + "arrow-body-style": [0], + "consistent-return": [0], + "generator-star-spacing": [0], + "global-require": [1], + "import/extensions": [0], + "import/no-extraneous-dependencies": [0], + "import/no-unresolved": [0], + "import/prefer-default-export": [0], + "jsx-a11y/no-static-element-interactions": [0], + "no-bitwise": [0], + "no-cond-assign": [0], + "no-else-return": [0], + "no-nested-ternary": [0], + "no-restricted-syntax": [0], + "no-use-before-define": [0], + "react/forbid-prop-types": [0], + "react/jsx-filename-extension": [1, { "extensions": [".js"] }], + "react/jsx-no-bind": [0], + "react/prefer-stateless-function": [0], + "react/prop-types": [0], + "require-yield": [1] + }, + "parserOptions": { + "ecmaFeatures": { + "experimentalObjectRestSpread": true + } + } +} diff --git a/.gitignore b/.gitignore index 00cbbdf..aa6e4c4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,59 +1,11 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. -# Compiled binary addons (http://nodejs.org/api/addons.html) -build/Release +# dependencies +/node_modules -# Dependency directories -node_modules/ -jspm_packages/ - -# Typescript v1 declaration files -typings/ - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env +# production +/dist +# misc +.DS_Store +npm-debug.log* diff --git a/.roadhogrc b/.roadhogrc new file mode 100644 index 0000000..32fe3f7 --- /dev/null +++ b/.roadhogrc @@ -0,0 +1,28 @@ +{ + "entry": "src/index.js", + "extraBabelPlugins": [ + ["module-resolver", { + "root": ["./src"], + "alias": { + "@": "./src" + } + }], + ["import", { + "libraryName": "antd-mobile", + "style": "css" + }] + ], + "env": { + "development": { + "extraBabelPlugins": [ + "dva-hmr", + "transform-runtime" + ] + }, + "production": { + "extraBabelPlugins": [ + "transform-runtime" + ] + } + } +} diff --git a/.roadhogrc.mock.js b/.roadhogrc.mock.js new file mode 100644 index 0000000..2554dd8 --- /dev/null +++ b/.roadhogrc.mock.js @@ -0,0 +1,3 @@ + +export default { +}; diff --git a/mock/.gitkeep b/mock/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/package.json b/package.json new file mode 100644 index 0000000..fd28079 --- /dev/null +++ b/package.json @@ -0,0 +1,34 @@ +{ + "private": true, + "scripts": { + "start": "roadhog server", + "build": "roadhog build", + "lint": "eslint --ext .js src test", + "precommit": "npm run lint" + }, + "engines": { + "install-node": "6.11.1" + }, + "dependencies": { + "babel-runtime": "^6.9.2", + "dva": "^2.1.0", + "react": "^15.4.0", + "react-dom": "^15.4.0" + }, + "devDependencies": { + "babel-eslint": "^7.1.1", + "babel-plugin-dva-hmr": "^0.3.2", + "babel-plugin-import": "^1.6.2", + "babel-plugin-module-resolver": "^3.0.0", + "babel-plugin-transform-runtime": "^6.9.0", + "eslint": "^3.12.2", + "eslint-config-airbnb": "^13.0.0", + "eslint-plugin-import": "^2.2.0", + "eslint-plugin-jsx-a11y": "^2.2.3", + "eslint-plugin-react": "^6.8.0", + "expect": "^1.20.2", + "husky": "^0.12.0", + "redbox-react": "^1.4.3", + "roadhog": "^1.2.1" + } +} diff --git a/public/.gitkeep b/public/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/app/common/config.js b/src/app/common/config.js new file mode 100644 index 0000000..e69de29 diff --git a/src/app/global/tabbar.js b/src/app/global/tabbar.js new file mode 100644 index 0000000..8cea6ef --- /dev/null +++ b/src/app/global/tabbar.js @@ -0,0 +1,79 @@ +import { + TabBar, + Icon +} from 'antd-mobile'; +import { routerRedux } from 'dva/router'; +import pathToRegexp from 'path-to-regexp'; + +const tabbarConf = { + tabbar: { + unselectedTintColor: "#949494", + tintColor: "#33A3F4", + barTintColor: "white" + }, + items: [{ + title: "Home", + key: "home", + icon: , + selectedIcon: + }, + { + title: "Friend", + key: "friend", + icon: , + selectedIcon: + }, + { + title: "Articles", + key: "articles", + icon: , + selectedIcon: + }, + { + title: "User", + key: "user", + icon: , + selectedIcon: + }] +}; + +class TabbarComponent extends React.Component { + constructor(props) { + super(props); + + const tabName = props.location.pathname.slice(1); + + this.state = { + selectedTab: tabName + }; + } + + handlePress = (key) => { + const { dispatch } = this.props; + this.setState({ + selectedTab: key + }); + dispatch(routerRedux.replace(`/${key}`)); + } + + render () { + return ( +
+ + {tabbarConf.items.map(conf => this.handlePress(conf.key)} + >{this.props.children})} + +
+ ); + } +} + +export default TabbarComponent; diff --git a/src/app/home/index.js b/src/app/home/index.js new file mode 100644 index 0000000..4d21163 --- /dev/null +++ b/src/app/home/index.js @@ -0,0 +1,18 @@ +import { connect } from 'dva'; + +const HomeComponent = ({username, password}) => { + return ( +
+ username: {username},
+ password: {password} +
+ ); +} + +function mapStateToProps ({home}) { + return { + ...home + }; +} + +export default connect(mapStateToProps)(HomeComponent); diff --git a/src/app/home/model/index.js b/src/app/home/model/index.js new file mode 100644 index 0000000..f3c6b7d --- /dev/null +++ b/src/app/home/model/index.js @@ -0,0 +1,28 @@ + +export default { + + namespace: 'home', + + state: { + username: 'xiaoming', + password: '55555' + }, + + subscriptions: { + setup({ dispatch, history }) { // eslint-disable-line + }, + }, + + effects: { + *fetch({ payload }, { call, put }) { // eslint-disable-line + yield put({ type: 'save' }); + }, + }, + + reducers: { + save(state, action) { + return { ...state, ...action.payload }; + }, + }, + +}; \ No newline at end of file diff --git a/src/app/layout.js b/src/app/layout.js new file mode 100644 index 0000000..ea28ade --- /dev/null +++ b/src/app/layout.js @@ -0,0 +1,23 @@ +import TabBar from './global/tabbar'; +import { connect } from 'dva'; +import { Router, Route, Switch, IndexRoute, Redirect } from 'dva/router'; +import Home from './home'; +import User from './user'; + +const Layout = (props) => { + return ( +
+ + + + + + + + + +
+ ); +} + +export default connect()(Layout); diff --git a/src/app/user/index.js b/src/app/user/index.js new file mode 100644 index 0000000..3e51bc7 --- /dev/null +++ b/src/app/user/index.js @@ -0,0 +1,9 @@ +import { connect } from 'dva'; + +const UserComponent = () => { + return ( +
User
+ ); +} + +export default UserComponent; diff --git a/src/assets/yay.jpg b/src/assets/yay.jpg new file mode 100644 index 0000000..e72bd8f Binary files /dev/null and b/src/assets/yay.jpg differ diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..a0bbb05 --- /dev/null +++ b/src/index.css @@ -0,0 +1,5 @@ + +html, body, :global(#root) { + height: 100%; +} + diff --git a/src/index.ejs b/src/index.ejs new file mode 100644 index 0000000..afba63d --- /dev/null +++ b/src/index.ejs @@ -0,0 +1,12 @@ + + + + + + Dva Demo + + + +
+ + diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..d3e67ea --- /dev/null +++ b/src/index.js @@ -0,0 +1,17 @@ +import dva from 'dva'; +import './index.css'; + +// 1. Initialize +const app = dva(); + +// 2. Plugins +// app.use({}); + +// 3. Model +app.model(require('app/home/model')); + +// 4. Router +app.router(require('./router')); + +// 5. Start +app.start('#root'); diff --git a/src/router.js b/src/router.js new file mode 100644 index 0000000..f5893a0 --- /dev/null +++ b/src/router.js @@ -0,0 +1,13 @@ +import React from 'react'; +import { Router, Route, Redirect } from 'dva/router'; +import Layout from 'app/layout'; + +function RouterConfig({ history }) { + return ( + + + + ); +} + +export default RouterConfig; diff --git a/src/utils/request.js b/src/utils/request.js new file mode 100644 index 0000000..6e8005c --- /dev/null +++ b/src/utils/request.js @@ -0,0 +1,30 @@ +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 })); +}