dva速览

南山隐士 2022年06月25日 30 0

什么是dva

dva 使用 redux 和 redux-saga 来使你更好的操作数据流, 并且还内置了 react-router, 以及 fetch, 它可以说是一个轻量级的应用框架, 使你更加方便得编写React 代码!

初始化

要想使用dva, 我们需要创建一个dva实例

dva()

// 初始化dva
const app = dva({
  history: createHashHistory({
    basename: '' // 这里可以设置基本的路径,如果你最终项目部署位置不在根目录, 需要改变
  })
})

初始化dva, 创建一个实例, 你可以操作一些内部封装的hock方法, 更多的配置

app.use()

你甚至可以使用一些插件来扩展 dva的 功能, 例如 使用 dva-loading, 我将在后面讲解这个插件的作用

import createLoading from 'dva-loading'
app.use(createLoading())

app.router()

你可以使用它来配置路由, 这里建议是通过一个文件来生成路由, 并且通过 dynamic 方法来生成动态路由, 更多你可以查看

import dynamic from 'dva/dynamic';

const UserPageComponent = dynamic({
  app,
  models: () => [
    import('./models/users'),
  ],
  component: () => import('./routes/UserPage'),
});

app.start()

你需要启动项目, 必须调用该方法, 它接受一个dom元素作为页面挂载的, 如果不传递, 将会返回JSX 元素的函数, 你可以使用它来放置到别的地方, 类似于你平时写一个App主组件一样, 例子中使用了国际化, 需要包裹主组件

// 传递dom
app.start('#root');

// 不传递
import { IntlProvider } from 'react-intl';
...
const App = app.start();
ReactDOM.render(<IntlProvider><App /></IntlProvider>, htmlElement);

Model

Model 是 dva 的核心功能, 它可以方便的操作管理数据状态, 它就是基于 redux 和 redux-saga 进行封装的, 如果你不熟悉 redux , 你可以查看这篇文章

namespace

model的命名空间, 同时也是他在全局 state 上的属性, 意思就是,它既是state中对应的key值也是我们创建model对应的名称, 我们在触发action 到 相应的 reducer 的时候, 需要使用到它, 它可以说是必须的

state

用于存放当前model中的state初始值, 需要注意的是,这里定义的值, 优先级低于在你创建dva实例通过 initialState属性 创建的值

看以下例子

const app = dva({
  initialState: { count: 1 },
});
app.model({
  namespace: 'count',
  state: 0,
});

最终初始值将会为 1

reducers

接收当前state以及action, 里面是用于描述应该如何去修改state的函数, ==这里是用于同步修改state的时候使用到的==, 函数定义的格式应该为:(state, action) => newState 或者 [(state, action) => newState, enhancer], action 就是包含了 当前action的名称, 以及最终你传递的参数, 这个参数可以说是你最终想修改成state的值,或者用它来改变state的值

image.png

reducers: {
// 定义了一个名为 loginSuccess 的 reducers
    loginSuccess(state, { payload }) {
      return {
        ...state,
        loggedIn: true,
        message: '',
        user: payload
      };
    }
  }

effects

用于异步去修改state的数据, 它接受 action 以及 effects, effects 它是一个对象, 里面内置了不少方法
image.png
我们主要需要使用到的是call、 put以及select

call

call 的作用处理异步, 就是因为有了它,我们才在effects 处理异步的一些操作, 它是一个函数, 第一个参数接受一个函数, 第二个参数接受该函数需要传递的参数, 你可以在这里发送一些ajax 请求

// call为请求的函数, payload就是传递的值
const { status, message, data } = yield call(login, payload);

put

put的作用在于触发action,而action又会触发对应的reducers, 从而达到state的更新, 试想一下, 当call 回来的数据后,我们想讲这个数据更新到state中, 此时pull 就可以帮我们实现这一点

yield put ({
    type:'xx/jj',
    payload:res
});
// xx 为对应model中的namespace的名称, jj 为对应 effects  和 reducers的方法名称(key)

需要注意的是, action 即可触发 effects 和 reducers, 所以尽量不要将取相同的名称, 先会找到effects 在找到 reducers, 如果有相同名称的情况下

select

用于从state中获取相关的数据,

// state是全局的state, data就是你需要的数据
const data = yield select(state=>state.data);

subscriptions

用于订阅一个数据源, 那么这个数据源可以是什么呢 ?
它可以是 当前的时间、服务器的 websocket 连接、keyboard 输入、geolocation 变化、history 路由变化等等,
你可以当这些数据有所变化的时候, 触发对应的dispatch,
定义格式应为: ({ dispatch, history }, done) => unlistenFunction

subscriptions: {
    setup({ history, dispatch }) {
      return history.listen(({ pathname }) => {
        if (pathname.indexOf('/sign/login') !== -1) {
          // 执行某些逻辑
        }
      });
    }
  },

例如我们可以在路由变化时候, 执行某些逻辑, 或者触发dispatch

Last Updated: 2022/06/25 19:16:34
React高级指引 React Hook速览