
前端【免费下载链接】dva React and redux based, lightweight and elm-style framework. (Inspired by elm and choo)项目地址https://gitcode.com/gh_mirrors/dv/dva点击查看免费下载导读docs/README.md是 dva 官方文档站的首页它以极简的方式定义了 dva 的三大核心卖点——易学易用仅 6 个 API、elm 概念用 reducers / effects / subscriptions 组织 model、插件机制如 dva-loading 自动处理 loading 状态并导航到快速上手、API、概念、知识地图等全部文档。本文以这份首页为骨架逐条展开三大特性的设计意图并结合packages/dva、packages/dva-core、packages/dva-loading等核心包源码给出实现级佐证帮助读者一次性建立文档在哪、特性是什么、源码如何支撑的完整认知。文档首页的结构一行 frontmatter 背后的文档体系docs/README.md的开头是一段 frontmatter 配置它决定了首页的呈现方式--- home: true actionText: 快速上手 → actionLink: /guide/ features: - title: 易学易用 details: 仅有 6 个 api对 redux 用户尤其友好配合 umi 使用后更是降低为 0 API - title: elm 概念 details: 通过 reducers, effects 和 subscriptions 组织 model简化 redux 和 redux-saga 引入的概念 - title: 插件机制 details: 比如 dva-loading 可以自动处理 loading 状态不用一遍遍地写 showLoading 和 hideLoading footer: MIT Licensed | Copyright © 2017-present ---其中actionLink: /guide/指向快速上手指南三条features则分别对应文档体系中三个最重要的主题。围绕这份首页docs/目录形成了一个完整的文档生态路径内容与首页特性的对应关系docs/api/README.md、docs/API.md输出文件、dva API、Model 五要素易学易用6 个 API 的完整定义docs/guide/concepts.md、docs/Concepts.md数据流向、State/Action/Reducer/Effect/Subscription、Router、Route Componentselm 概念模型组织的设计哲学docs/guide/getting-started.mddva-cli 安装、建项目、antd、路由、Model、connect、构建快速上手入口对应的实操教程docs/guide/develop-complex-spa.md动态加载 model、跨 model 通信、任务调度、长流程、测试elm 概念在复杂业务中的进阶应用docs/guide/fig-show.md从 React → Redux → Saga → Dva 的四步图解elm 概念的可视化理解docs/guide/examples-and-boilerplates.md官方与社区示例、脚手架三大特性的落地案例docs/knowledgemap/README.mdES6、React、dva 的最小知识集易学易用学习路径的最小集合下文按首页声明的三条主线展开并在每条主线中引入对应的深层文档与源码证据。特性一易学易用 —— 仅有 6 个 API 的框架面首页的第一条特性是仅有 6 个 api对 redux 用户尤其友好。dva 将 redux 生态中分散的 store、reducer、saga、middleware 概念收敛成一个极小的 API 面。结合 docs/api/README.md 与 docs/API.md核心 API 面如下app dva(opts)—— 创建应用const app dva({ history, // 指定给路由用的 history默认是 hashHistory initialState, // 指定初始数据优先级高于 model 中的 state默认是 {} onError, onAction, onStateChange, onReducer, onEffect, onHmr, // hooks extraReducers, // 额外的 reducer extraEnhancers, // 额外的 StoreEnhancer });history默认值为hashHistory。切换为browserHistory的写法在 docs/guide/knowledgemap 对应章节 与 API 文档中均有示例import createHistory from history/createBrowserHistory后传入history: createHistory()。initialState优先级高于 model 内部声明的state。例如dva({ initialState: { count: 1 } })搭配app.model({ namespace: count, state: 0 })时app.start()后state.count为 1。从源码看packages/dva/src/index.js 中opts.history || createHashHistory()直接印证了默认 hashHistory的实现并且把router: connectRouter(history)作为initialReducer注入同时注册routerMiddleware(history)这正是 dva 能把路由状态同步进 store 的底层机制。app.use(hooks)与app.model(model)/app.unmodel(namespace)/app.replaceModel(model)app.use(hooks)配置 hooks 或注册插件插件最终返回的是 hooks例如app.use(createLoading(opts))注册 dva-loading。app.model(model)注册 model是使用频率最高的 API。app.unmodel(namespace)取消 model 注册清理 reducers、effects 和 subscriptions。若 subscription 没有返回 unlisten 函数会给出警告。源码实现在 packages/dva-core/src/index.js删除 asyncReducers 与 reducers、replaceReducer、派发dva/UPDATE、派发namespace/CANCEL_EFFECTS取消 saga最后从_models中移除。app.replaceModel(model)仅在app.start()之后可用按 namespace 比较命中则替换清理旧 effects/reducers/subscriptions 但保留旧 state未命中则等同于app.model对 HMR 非常有用见 packages/dva-core/src/index.js。app.router(config)与app.start(selector?)import { Router, Route } from dva/router; app.router(({ history }) ( Router history{history} Route path/ component{App} / /Router )); app.start(#root); // 传 selector 则自动渲染 // 不传 selector 时返回一个返回 JSX 的函数 // const App app.start(); ReactDOM.render(App /, htmlElement);app.start不传selector的常见场景包括测试、node 端、react-native 以及 react-intl 国际化包装。源码中 packages/dva/src/index.js 会校验 container 是否 HTMLElement、路由是否已注册且用ReactDOM.createRoot(...).render(...)挂载。输出文件dva/router、dva/fetch、dva/saga、dva/dynamic除默认导出外dva 还提供若干子路径导出方便按需引入dva/router路由相关 API当前仓库实现中由react-router-dom与connected-react-router提供routerRedux通过命名导出暴露见 packages/dva/src/index.js。dva/fetch异步请求库导出isomorphic-fetch的 API不和 dva 强绑定可自由选择其他请求库。dva/saga导出 redux-saga 的 API主要用于编写用例用例中需要用到 effects。dva/dynamic动态加载 React Component 和 dva model 的工具方法import dynamic from dva/dynamic; const UserPageComponent dynamic({ app, // dva 实例加载 models 时需要 models: () [ import(./models/users) ], // 返回 Promise 数组的函数Promise 返回 dva model component: () import(./routes/UserPage), // 返回 Promise 的函数Promise 返回 React Component });其实现见 packages/dva/src/dynamic.js通过Promise.all同时解析 models 与 component逐个调用app.model(model)注册带cached去重并支持dynamic.setDefaultLoadingComponent(...)配置加载态组件。说明仅 6 个 API是官方对核心 API 面的概括dva / app.use / app.model / app.unmodel / app.router / app.start配合 umi 使用后官方宣称进一步降为 0 APIdocs 体系中的 API 文档 还额外给出了app.replaceModel等能力。特性二elm 概念 —— 用 reducers、effects 和 subscriptions 组织 model首页的第二条特性是通过 reducers, effects 和 subscriptions 组织 model简化 redux 和 redux-saga 引入的概念。这是 dva 的灵魂docs/Concepts.md 与 docs/guide/concepts.md 给出了完整定义。数据流向dva 的数据流向非常清晰数据的改变通常由用户交互或浏览器行为如路由跳转触发通过dispatch发起一个 action同步行为直接经Reducers改变State**异步行为副作用**先触发Effects再流向Reducers最终改变State。整套思路与开源社区保持一致。model 的 5 个属性以 API 文档中的 todo 示例为例app.model({ namespace: todo, state: [], reducers: { add(state, { payload: todo }) { // 保存数据到 state这是唯一修改 state 的地方 return [...state, todo]; }, }, effects: { *save({ payload: todo }, { put, call }) { // 调用 saveTodoToServer成功后触发 add action 保存到 state yield call(saveTodoToServer, todo); yield put({ type: add, payload: todo }); }, }, subscriptions: { setup({ history, dispatch }) { // 监听 history 变化当进入 / 时触发 load action return history.listen(({ pathname }) { if (pathname /) { dispatch({ type: load }); } }); }, }, });namespacemodel 的命名空间同时也是它在全局 state 上的 key只能用字符串不支持通过.创建多层命名空间详见 checkModel 的校验逻辑。state初始值优先级低于dva()的opts.initialState。reducerskey/value 格式唯一可以修改 state 的地方由 action 触发。格式为(state, action) newState或[(state, action) newState, enhancer]。必须保持纯函数与不可变数据这也是热重载和时间旅行能工作的前提。对应测试见 packages/dva-core/test/reducers.test.js。effectskey/value 格式处理异步操作与业务逻辑不直接修改 state。格式为*(action, effects) void或[*(action, effects) void, { type }]。对应测试见 packages/dva-core/test/effects.test.js。subscriptionskey/value 格式订阅一个数据源当前时间、websocket、键盘输入、geolocation 变化、history 路由变化等在app.start()时执行格式为({ dispatch, history }, done) unlistenFunction。若要使用app.unmodel()subscription 必须返回 unlisten 方法。Effect 的 5 种调度类型API 文档列出 effect 的type支持takeEvery、takeLatest、throttle、watcher、poll五种。源码 packages/dva-core/src/getSaga.js 对此给出了精确实现takeEvery默认每个 action 都会触发一次 effect。takeLatest同一 key 下只保留最新一次执行。throttle节流要求配置opts.ms源码中有invariant(opts.ms, ...)断言。watcher把 effect 本身当作 watcher saga 使用直接执行sagaWithCatch。poll轮询要求配置opts.delay内部用take(key-start)与race([...])组合实现启动/停止控制。Subscription 订阅示例import key from keymaster; app.model({ namespace: count, subscriptions: { keyEvent({ dispatch }) { key(⌘up, ctrlup, () { dispatch({ type: add }) }); }, }, });subscription 在app.start()时由 packages/dva-core/src/subscription.js 的runSubscription统一执行返回的 unlisten 函数被登记到unlisteners表供unmodel/replaceModel清理时调用见 packages/dva-core/src/index.js。进阶复杂 SPA 中的 model 运用docs/guide/develop-complex-spa.md围绕 elm 概念展开了一组实战主题可以作为本特性的延伸阅读动态加载 model利用require.ensure在路由切换时registerModel(app, require(./models/dashboard))避免启动时全量加载。跨 model 共享与通信一个 effect 内yield select()可以读取其他 model 的 state通过yield call({ type: a/foo })指定 namespace 组合多个 model 的流程用yield take(a/service1Success)在外部向某个 effect 流程中插入并行逻辑。多任务调度yield all([call(a), call(b)])并行、yield race({...})竞争如用 1 秒空操作实现请求超时、串行逐个yield call。长流程一个 effect 中多次yield put驱动 reducer 分步更新借助createPromiseMiddleware见 packages/dva-core/src/createPromiseMiddleware.js在组件中 dispatch effect 会返回 Promise可以把resolve/reject传入 action实现跨组件、跨 model 的长流程回调。特性三插件机制 —— 以 dva-loading 为例剖析 hooks首页的第三条特性是插件机制比如 dva-loading 可以自动处理 loading 状态不用一遍遍地写 showLoading 和 hideLoading。插件的本质返回 hooks 的对象在 packages/dva-core/src/Plugin.js 中定义了全部受支持的 hooksHook触发时机典型用途onError((err, dispatch) {})effect 执行错误或 subscription 通过done主动抛错时全局错误处理如 antdmessage.erroronAction(fn \| fn[])action 被 dispatch 时注册 redux 中间件如 redux-loggeronStateChange(fn)state 改变时同步 state 到 localStorage / 服务端onReducer(fn)封装 reducer 执行实现 redo/undo如 redux-undoonEffect(fn)封装 effect 执行自动 loading 状态如 dva-loadingonHmr(fn)热替换相关HMR如 babel-plugin-dva-hmrextraReducers指定额外的 reducer集成 redux-form 的formreducerextraEnhancers指定额外的 StoreEnhancer集成 redux-persist 的持久化_handleActions内部 handleActions 扩展内部使用插件在app.use(plugin)时被压入 hooks 数组Plugin.jsstart()时通过plugin.get(onReducer)、plugin.get(extraReducers)等聚合生效packages/dva-core/src/index.js。dva-loading 源码剖析packages/dva-loading/src/index.js 完整实现了首页描述的能力它只依赖两个 hookextraReducers注册loading命名空间的 reducerstate 结构为{ global, models, effects }内部派发DVA_LOADING/SHOW/DVA_LOADING/HIDE两个内部 action 来置位/复位。onEffect包装每个 effect执行前put(SHOW)执行后put(HIDE)从而自动追踪每个 effect 的 loading 状态无需手写 showLoading / hideLoading。它还支持两个配置项only只处理指定 actionType与except排除指定 actionType两者同时配置会抛出歧义错误第 9-11 行并可用opts.namespace自定义 loading 状态的挂载 key。其他插件与示例仓库中还包含packages/dva-immer通过_handleActions让 reducer 支持用 immer 的produce写法简化不可变更新examples/with-immer 提供了配套的完整示例入口dva.js与model.js。examples/user-dashboard用户管理后台示例其中的 plugins/onError.js 展示了自定义 onError 插件的标准写法dispatch 失败 action 而非直接 throw。examples/with-redux-undo展示了onReducer结合 redux-undo 实现撤销/重做的用法API 文档给出了带 routing 还原的完整代码。插件机制让框架保持精简、能力按需扩展成为可能——这正是首页 footer 与 文档首页 之外仓库里packages/多包结构的根本原因。快速上手从文档首页到第一个应用首页的actionText: 快速上手 →直接指向 docs/guide/getting-started.md。其核心流程如下安装 dva-cli版本需0.9.1及以上$ npm install dva-cli -g $ dva -v dva-cli version 0.9.1创建并启动应用$ dva new dva-quickstart $ cd dva-quickstart $ npm start浏览器打开 http://localhost:8000 即可看到欢迎页。定义路由与组件新建routes/Products.js并在router.js注册Route path/products exact component{Products} /。定义 model 与 connect// models/products.js export default { namespace: products, state: [], reducers: { delete(state, { payload: id }) { return state.filter(item item.id ! id); }, }, };// routes/Products.js import { connect } from dva; // ... 组件实现 export default connect(({ products }) ({ products }))(Products);构建应用$ npm run build构建产物输出到dist/目录。仓库中的examples/目录提供了多种可直接运行的最小示例examples/func-test基础脚手架、examples/user-dashboard用户管理、examples/with-react-router-3、examples/with-redux-undo、examples/with-nextjs、examples/with-immer覆盖了不同技术组合下的接入方式。知识地图最小知识集docs/knowledgemap/README.md回答了初学者最常见的疑问es6 特性那么多我需要全部学会吗reducer 的增删改应该怎么写怎么做全局/局部的错误处理。它梳理了基于 dva 开发的最小知识集包括JavaScript 语言const/let、模板字符串、默认参数、箭头函数、import/export、解构赋值、对象字面量改进、Spread Operator、Promises、Generators——其中 Generators 是 effects 的底层yield把异步逻辑以同步方式组织起来。React ComponentStateless Functional Components、JSX、props 与 propTypes、CSS Modules、classnames。Reducer增删改的标准写法concat/filter/map并明确建议最多一层嵌套保持 state 扁平化同时给出深层嵌套的反例。Effectput触发 action、call调用异步逻辑、select从 state 取数全局错误处理走onError局部特殊处理用try/catch。Subscription异步数据初始化history.listen匹配/users触发users/fetch复杂 URL 规则推荐path-to-regexp。RouterRoute Components 的 connect 绑定、基于routerRedux.push的 action 式页面跳转。dva 配置onAction添加 redux 中间件支持数组、切换browserHistory的完整步骤。这份地图与本文第一部分的三条主线一一呼应知识地图服务于易学易用model 五要素服务于elm 概念而 hooks 配置与中间件注册服务于插件机制。社区与许可文档首页末尾是社区入口包括官方 Slack 交流群、GitHub Issue问题反馈与 FAQ、钉钉群与微信群二维码形式以及官方 Telegram 频道。技术问题优先通过 GitHub Issue 检索和提问历史 FAQ 已沉淀了大量实践结论。整个项目以 MIT 协议开源footer: MIT Licensed | Copyright © 2017-present许可证文件见仓库根目录 LICENSE。小结从docs/README.md这一页出发可以完整地看到 dva 的设计主线以 6 个 API 收敛 redux redux-saga react-router 的复杂度易学易用以 reducers / effects / subscriptions 统一建模elm 概念以 hooks 插件机制保持核心精简、能力按需扩展插件机制。对应地文档体系提供了 API 参考、概念详解、快速上手、复杂 SPA 实战 和 知识地图 五类资料而packages/下的 dva、dva-core、dva-loading、dva-immer 则为上述每一项特性提供了可直接阅读的实现证据。建议读者按首页三条特性 → 对应概念/API 文档 → 对应源码的路径逐步深入。赞分享前端【免费下载链接】dva React and redux based, lightweight and elm-style framework. (Inspired by elm and choo)项目地址https://gitcode.com/gh_mirrors/dv/dva点击查看免费下载相关推荐Graphcool框架核心概念函数与事件机制深度解析Graphcool框架核心概念函数与事件机制深度解析 引言GraphQL与无服务器架构的完美结合 在现代应用开发中Graphcool框架通过巧妙结合GraDVA核心概念详解模型、状态管理与数据流机制DVA核心概念详解模型、状态管理与数据流机制 DVA框架基于Redux、Redux Saga和React Router构建通过引入8个核心概念State、前端ARK-radar-hack版本更新日志2024年最新功能和修复内容详解ARK radar hack版本更新日志2024年最新功能和修复内容详解 ARK radar hack作为ARK Survival Evolved游戏的终极辅上一篇【亲测免费】 Lyciumaker在线三国杀卡牌制作器轻松打造个性化卡牌下一篇AltoroJ展示Web应用安全漏洞的样本银行应用创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考