[关闭]
@duanyubin 2016-03-20T15:50:58.000000Z 字数 3873 阅读 350

跑步系统项目总结

项目总结


  1. SPA
  2. Redux
  3. Global css && import css library
  4. Eslint
  5. Debug
  6. Error handler
  7. Problems

Redux

  1. /**
  2. * 下方是reducer, 一个通过旧的`state`和已经触发的`action`生成新`state`的纯函数
  3. *
  4. * `state`的形状由业务决定,可以是数组或者对象,**重要的是,不可以修改state对象,而是返回一个新的对象**
  5. *
  6. */
  7. function counter(state = 0, action) {
  8. switch (action.type) {
  9. case 'INCREMENT':
  10. return state + 1
  11. case 'DECREMENT':
  12. return state - 1
  13. default:
  14. return state
  15. }
  16. }
  17. // 创建store用于存放整个app的所有state.
  18. // Its API is { subscribe, dispatch, getState }.
  19. let store = createStore(counter)
  20. // 可以手动订阅更新或者跟view层绑定
  21. store.subscribe(() =>
  22. console.log(store.getState())
  23. )
  24. // 触发action
  25. store.dispatch({ type: 'INCREMENT' })
  26. // 1
  27. store.dispatch({ type: 'INCREMENT' })
  28. // 2
  29. store.dispatch({ type: 'DECREMENT' })
  30. // 1

Action

  1. {
  2. type: ADD_TODO,
  3. payload: {
  4. text: 'Build my first Redux app'
  5. }
  6. }

Action Creators

  1. function addTodo(text) {
  2. return {
  3. type: ADD_TODO,
  4. payload: {
  5. text
  6. }
  7. };
  8. }
  9. // 实际发送 action
  10. dispatch(addTodo(text));
  11. function removeTodo(id) {
  12. return (dispatch, getState) => {
  13. return ajax()
  14. .then((json) => {
  15. dispatch({
  16. type: REMOVE_TODO,
  17. id
  18. })
  19. })
  20. }
  21. }
  22. dispatch(removeTodo(id));

Middleware

It provides a third-party extension point between dispatching an action, and the moment it reaches the reducer.
dispatch一个action和此action到达reducer时,给第三方扩展提供切入点。
用于日志记录,异常处理,异步处理,路由等。

Redux && React

项目目录

  1. |-- actions
  2. |-- components
  3. |-- containers
  4. |-- middleware
  5. |-- reducers
  6. |-- routes
  7. |-- configureStore.js
  8. |-- index.jsx

Container

负责与redux交流的一个react component

react-redux提供了 Provider元件和connect方法

Provider

用在应用的根元素外面,负责传递唯一的Store给应用

  1. const reducer = combineReducers(reducers);
  2. const store = createStore(reducer);
  3. class App extends Component {
  4. render() {
  5. return (
  6. <Provider store={store}>
  7. {() => <App />}
  8. </Provider> );
  9. }
  10. }

connect

  1. 将dispatch方法透过props的方式加到元件中
  2. 选取这个container需要state的哪一部分
  1. import { increase, decrease}
  2. function mapStateToProps(state) {
  3. return { counter: state.counter };
  4. }
  5. function mapDispatchToProps() {
  6. return {
  7. increase: increase,
  8. decrease
  9. }
  10. }
  11. class CounterApp {
  12. render() {
  13. const { counter, dispatch } = this.props;
  14. return (
  15. <Counter counter={counter} /> );
  16. }
  17. }
  18. export default connect(mapStateToProps, mapDispatchToProps)(CounterApp)

CSS Library

before:

  1. // users.scss
  2. @include foundation-button;
  3. @include foundation-forms;
  4. // detail.scss
  5. @include foundation-forms;

after:

  1. // mian.scss
  2. :global {
  3. @include foundation-form-prepostfix;
  4. @include foundation-text-alignment;
  5. @include foundation-global-styles;
  6. ....
  7. }
  8. // User.jsx
  9. <div styleName="wrap">
  10. <a className="button small" onClick={this.handleAddClick}>添加新用户</a>
  11. </div>

ESLint

javascript style

Debug

Redux devTools
React devTools

Error Handler

  1. // action.js
  2. function requestCodes(id, pageNum = 1, dispatch) {
  3. // return ajax({ url: `http://localhost:3100/inviteCodes.json` })
  4. return ajax({
  5. url: `http://baoming.ws.netease.com/admin/invitecode/list`,
  6. body: { cid: id, pageNum }
  7. })
  8. .then((json) => {
  9. dispatch({
  10. type: type.REQUEST_CODES,
  11. data: json.data,
  12. id
  13. });
  14. return Promise.resolve(json);
  15. }).catch(errorHandler.bind(null, dispatch));
  16. }
  17. // 获取邀请码
  18. export function loadInviteCodes(id, pageNum) {
  19. return (dispatch) => {
  20. return requestCodes(id, pageNum, dispatch);
  21. };
  22. }
  23. // 获取邀请码总数
  24. export function fetchCodesCount(id) {
  25. return (dispatch) => {
  26. // return ajax({ url: `http://localhost:3100/count.json` })
  27. return ajax({
  28. url: `http://baoming.ws.netease.com/admin/invitecode/totalCount`,
  29. body: { cid: id }
  30. })
  31. .then((json) => {
  32. dispatch({
  33. type: type.REQUEST_CODES_COUNT,
  34. count: json.data
  35. });
  36. return Promise.resolve(json);
  37. });
  38. };
  39. }
  40. // errorHandler
  41. import * as modal from '../actions/modal';
  42. export default function errorHanlder(dispatch, fail) {
  43. dispatch(modal.error({ msg: `${fail.msg}` }));
  44. if (fail.code === -1 && window.location.hostname !== 'localhost') {
  45. setTimeout(() => {
  46. window.location.href = 'http://baoming.ws.netease.com/login/login';
  47. }, 500);
  48. }
  49. const error = new Error(fail);
  50. throw error;
  51. }

Problems

  1. 代码实现思路不统一
  2. unit test
  3. confirm modal
  1. // before
  2. // action.js
  3. function whatever() {
  4. if(confirm('something')){
  5. //....
  6. }
  7. }
  8. // after
  9. // action.js
  10. function whatever(){
  11. modal.confirm('something')
  12. .then((result) => {
  13. console.log(result)
  14. })
  15. }
  16. // modal.js
  17. const resolve = () => {}
  18. const reject = () => {}
  19. const promise = new Promise((res, rej) => {
  20. resolve = res
  21. reject = rej
  22. })
  23. function show() {}
  24. function hide(result) {
  25. resolve(result)
  26. }
  27. export function confirm(msg) {
  28. return promise
  29. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注