Skip to content

基本计数器 ​

本节目标:理解“基本计数器”的核心思路,并能把它用于实际开发或面试表达。 使用


Src/index.js
import

React from

'react';
import
dva,

{ connect } from

'./dva';
const

app =

dva();
app.model({

namespace:

'counter',

// 每个命名空间都有自己的状态 state: { number: 0 },// 还有自己的处理器reducerreducers: {// reducers对象key就相当于actionType// 值是本state对应的处理函数 // state是此命名空间下的分状态,

add(state,
action)

{return { number:

state.number

+ 1 };},

minus(state,
action)

{return { number:

state.number

- 1 };}

}
});
function
Counter(props)

{return (

<div>
<p>{props.number}</p>
<button
onClick={()

=\>

props.dispatch({
       `type:` `'counter/add'`
})}
>+</button>
</div>
)
}
const

ConnectedCounter =

connect(

//conenct第二个参数如果没有传,默认会把store.dispatch当成参数传给组件 state =\>

state.counter
)(Counter);
//

定义要渲染的内容

app.router(()

=\>

<ConnectedCounter
/>);
//

开始渲染

app.start('#root');

实现


src\dva\index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, combineReducers } from 'redux';
import { Provider, connect } from 'react-redux';
import prefixNamespace from './prefixNamespace';
export { connect }
function dva() {
  const app = {
    //

存放model的数组

    _models: [],
    //

函数,用来往model数组中添加model元素

    model,
    //

定义路由的函数

    router,
    //

存放路由函数的变量

    _router: null,
    //

开启渲染

    start
  }
  function model(modelObject) {
    const prefixedModel = prefixNamespace(modelObject);
    app._models.push(prefixedModel);
    return prefixedModel
  }
  function router(routerConfig) {
    app._router = routerConfig;
  }
  let initialReducers = {};
  function start(selector) {
    for (const model of app._models) {
      initialReducers[model.namespace] = getReducer(model);
    }
    let rootReducer = createReducer();
    let store = createStore(rootReducer);
    ReactDOM.render(
      <Provider store={store}>
        {app._router()}
      </Provider>, document.querySelector(selector)
    );
  }
  function createReducer() {
    return combineReducers(initialReducers);
  }
  return app;
}
function getReducer(model) {
  let { state: initialState, reducers } = model;
  return (state = initialState, action) => {
    let reducer = reducers[action.type];
    if (reducer) return reducer(state, action);
    return state;
  }
}
export default dva;
/**
 * connect => Provider
 * Provider => store
 * store => reducer
 *

获取每个model的reducers对象,把每个对象变成一个函数

 *

然后再通过combineReducers合并成一个

reducer
 */

src\dva\prefixNamespace.js

import { NAMESPACE_SEP } from './constants';
/**
 *

把一个对象的key从一个老的值变成

 namespace/

老的值

 * @param {*} obj
 * @param {*} namespace
 */
function prefix(obj, namespace) {
  //[add,minus]
  return Object.keys(obj).reduce(function (memo, key) {
    const newKey = `${namespace}${NAMESPACE_SEP}${key}`;
    memo[newKey] = obj[key];
    return memo;
  }, {});
}
export default function prefixNamespace(model) {
  if (model.reducers) {
    model.reducers = prefix(model.reducers, model.namespace);
  }
  return model;
}
src\dva\constants.js
export const NAMESPACE_SEP = '/';

本站总访问 — 次