绑定并转换action的方法。

先看源码:

  1. function bindActionCreator(actionCreator, dispatch) {
  2. return function() {
  3. return dispatch(actionCreator.apply(this, arguments))
  4. }
  5. }
  6. export default function bindActionCreators(actionCreators, dispatch) {
  7. if (typeof actionCreators === 'function') {
  8. return bindActionCreator(actionCreators, dispatch)
  9. }
  10. const boundActionCreators = {}
  11. for (const key in actionCreators) {
  12. const actionCreator = actionCreators[key]
  13. if (typeof actionCreator === 'function') {
  14. boundActionCreators[key] = bindActionCreator(actionCreator, dispatch)
  15. }
  16. }
  17. return boundActionCreators
  18. }

整个源码并不多,看起来就是遍历actions并绑定,再将dispatch传入。

为了更方便理解,我们需要结合DEMO深入理解:

  1. // userActions.js
  2. export const f1 = function (id) {
  3. return function (dispatch: any, getState: any) {
  4. console.log('f1');
  5. request({ id });
  6. return getState();
  7. };
  8. };
  9. export const f2 = function (id) {
  10. return function (dispatch: any, getState: any) {
  11. console.log('f1');
  12. request({ id });
  13. return getState();
  14. };
  15. };

引入:

  1. // connect.js
  2. import * as usersActions from './userActions'
  3. function defaultMapStateToProps(state) {
  4. return {
  5. $user: state.user,
  6. };
  7. }
  8. function defaultMapDispatchToProps(dispatch: any) {
  9. return {
  10. actions: {
  11. $user: bindActionCreators(Object.assign({}, usersActions), dispatch),
  12. }
  13. }
  14. }
  15. export default function createContainer() {
  16. const curMapStateToProps: any = defaultMapStateToProps;
  17. const curMapDispatchToProps: any = defaultMapDispatchToProps;
  18. return function connectAppScreen(constructor) {
  19. return connect(curMapStateToProps, curMapDispatchToProps)(constructor);
  20. }
  21. }

在react组件调用action

  1. @connect
  2. class App extends React.Component {
  3. fetch(){
  4. this.props.$actions.$user.f1('id1')
  5. }
  6. }

最小化代码实现

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <script>
  11. function bindActionCreator(actionCreator, dispatch) {
  12. return function() {
  13. return dispatch(actionCreator.apply(this, arguments))
  14. }
  15. }
  16. function bindActionCreators(actionCreators, dispatch) {
  17. if (typeof actionCreators === 'function') {
  18. return bindActionCreator(actionCreators, dispatch)
  19. }
  20. const boundActionCreators = {}
  21. for (const key in actionCreators) {
  22. const actionCreator = actionCreators[key]
  23. if (typeof actionCreator === 'function') {
  24. boundActionCreators[key] = bindActionCreator(actionCreator, dispatch)
  25. }
  26. }
  27. return boundActionCreators
  28. }
  29. const dispatch = function(action) {
  30. console.log('dispatch.action', action);
  31. return action;
  32. }
  33. const actions = {
  34. f1: (params) => {
  35. return (dispatch) => {
  36. console.log('f1.params', params)
  37. dispatch({type: 'F1', payload: 'f1'})
  38. }
  39. },
  40. f2: (params) => {
  41. return (dispatch) => {
  42. console.log('f2.params', params)
  43. dispatch({type: 'F2', payload: 'f2'})
  44. }
  45. }
  46. }
  47. const a1 = bindActionCreators(actions, func => func(dispatch));
  48. console.log('a1', a1)
  49. a1.f1('xx f1');
  50. a1.f2('bb f2');
  51. </script>
  52. </body>
  53. </html>