【react框架之dvajs】dva数据流你可能还不知道的subscriptions隐藏的秘密

Subscriptions 是一种从 源 获取数据的方法,它来自于 elm。 语义是订阅,用于订阅一个数据源,然后根据条件 dispatch 需要的 action。数据源可以是当前的时间、服务器的 websocket连接、keyboard 输入、geolocation 变化、history 路由变化等等。

简单点说,就是在里面写的方法,在页面一加载的时候就会执行。

  • 方法是普通函数,不能是getor函数
  • 实参有dispatch/history两个属性
  • history:包含路由跳转监听的history对象
  • dispatch: 派发reducer里面的同步方法

实现效果

请添加图片描述

代码分析

import key from "keymaster";

const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
export default {
    
    
  namespace: "products",
  state: {
    
    
    count: 0,
    lists: [
      {
    
     name: "dva", id: 1 },
      {
    
     name: "antd", id: 2 },
    ],
  },
  // 同步更新的方法
  reducers: {
    
    
    delete(state, {
    
     id }) {
    
    
      return {
    
    
        ...state,
        lists: state.lists.filter((item) => item.id !== id),
      };
    },
    addCount(state) {
    
    
      return {
    
     ...state, count: state.count + 1 };
    },
    minusCount(state) {
    
    
      return {
    
     ...state, count: state.count - 1 };
    },
  },

  effects: {
    
    
    // *addCountAsync(action, effects) {
    
    
    //   const { put, select, call } = effects;
    //   const data = yield select();
    //   console.log("我被点击了");
    //   yield call(delay, 2000);
    //   yield put({ type: "addCount" });
    // },

    // 设置不同类型的监听器,监听器类型有takeLatest, takeEvery, throttle, debounce
    addCountAsync: [
      function* (action, effects) {
    
    
        const {
    
     put, call } = effects;
        yield call(delay, 2000);
        yield put({
    
     type: "addCount" });
      },
      {
    
    
        type: "takeLatest",
      },
    ],
    *minusCountAsync(action, effects) {
    
    
      const {
    
     put, call } = effects;
      yield call(delay, 2000);
      yield put({
    
     type: "minusCount" });
    },
  },
  subscriptions: {
    
    
    async init(params) {
    
    
      const {
    
     dispatch } = params;
      console.log("初始化被执行了", params);
      await delay(2000);
      dispatch({
    
     type: "addCount" });
    },
    setup(params) {
    
    
      console.log("订阅被执行了", params);
    },
    keyEvent({
     
      dispatch }) {
    
    
      key("⌘+up, ctrl+up", () => {
    
    
        dispatch({
    
     type: "addCount" });
      });

      key("⌘+down, ctrl+down", () => {
    
    
        dispatch({
    
     type: "minusCount" });
      });
    },
  },
};

页面初始化后,自动diapatchaddCount方法。数据+1。

另外我们也注册了键盘事件keyEvent

请添加图片描述

  • 注意点
    • init及setup都只会初始化执行一次,后续不会再执行
    • 要做路由监听,需要使用history.listen,第一次会执行,之后每次路由切换的时候都会调用。

请添加图片描述
可以在这里做针对页面切换时的业务处理。对location进行结构,获取pathname,对具体的路由进行监测即可。

async init(params) {
    
    
 const {
    
     dispatch, history } = params;
 console.log("初始化被执行了", params);
 await delay(2000);
 dispatch({
    
     type: "addCount" });
 // 返回一个函数,用于在组件卸载时取消监听
 const unListen = history.listen((location) => {
    
    
   if (location.pathname === "/product") {
    
    
     dispatch({
    
     type: "addCount" });
     //  移除监听
     unListen();
   }
   console.log("监听被执行了", location);
 });
}

请添加图片描述

猜你喜欢

转载自blog.csdn.net/qq_27702739/article/details/143575631