博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
又一轮子?Typescript+React+Redux,放弃saga,支持服务器渲染同构
阅读量:6757 次
发布时间:2019-06-26

本文共 4136 字,大约阅读时间需要 13 分钟。

  • 你是原生Redux用户?有没有觉得写Redux太繁琐了?
  • 你是dvaJS用户?有没有觉得redux-saga概念太多,且yield无法返回TS类型?

试试react-coat吧:

项目地址:

// 仅需一个类,搞定 action、reducer、effect、loadingclass ModuleHandlers extends BaseModuleHandlers {  @reducer  protected putCurUser(curUser: CurUser): State {    return {...this.state, curUser};  }  @reducer  public putShowLoginPop(showLoginPop: boolean): State {    return {...this.state, showLoginPop};  }  @effect("login") // 使用自定义loading状态  public async login(payload: {username: string; password: string}) {    const loginResult = await sessionService.api.login(payload);    if (!loginResult.error) {      this.updateState({curUser: loginResult.data});      Toast.success("欢迎您回来!");    } else {      alert(loginResult.error.message);    }  }  // uncatched错误会触发@@framework/ERROR,监听并发送给后台  @effect(null) // 不需要loading,设置为null  protected async ["@@framework/ERROR"](error: CustomError) {    if (error.code === "401") {      this.dispatch(this.actions.putShowLoginPop(true));    } else if (error.code === "301" || error.code === "302") {      this.dispatch(this.routerActions.replace(error.detail));    } else {      Toast.fail(error.message);      await settingsService.api.reportError(error);    }  }  // 监听自已的INIT Action,做一些异步数据请求  @effect()  protected async ["app/INIT"]() {    const [projectConfig, curUser] = await Promise.all([      settingsService.api.getSettings(),      sessionService.api.getCurUser()    ]);    this.updateState({      projectConfig,      curUser,    });  }}

react-coat 特点

  • 集成 react、redux、react-router、history 等相关框架
  • 仅为以上框架的糖衣外套,不改变其基本概念,无强侵入与破坏性
  • 结构化前端工程、业务模块化,支持按需加载
  • 同时支持 SPA(单页应用)和 SSR(服务器渲染)
  • 使用 typescript 严格类型,更好的静态检查与智能提示
  • 开源微框架,源码不到千行,几乎不用学习即可上手

与 Dva 的异同

  • 引入 ActionHandler 观察者模式,更优雅的处理模块之间的协作
  • 去除 redux-saga,使用 async、await 替代,简化代码的同时对 TS 类型支持更全面
  • 原生使用 typescript 组织和开发,更全面的类型安全
  • 路由组件化、无 Page 概念、更自然的 API 和更简单的组织结构
  • 更大的灵活性和自由度,不强封装脚手架等
  • 支持 SPA(单页应用)和 SSR(服务器渲染)快速切换,
  • 支持模块异步按需加载和同步加载快速切换
差异示例:使用强类型组织所有 reducer 和 effect
// Dva中常这样写dispatch({ type: 'moduleA/query', payload:{username:"jimmy"}} })//本框架中可直接利用ts类型反射和检查:this.dispatch(moduleA.actions.query({username:"jimmy"}))
差异示例:State 和 Actions 支持继承
// Dva不支持继承// 本框架可以直接继承class ModuleHandlers extends ArticleHandlers
{ constructor() { super({}, {api}); } @effect() protected async parseRouter() { const result = await super.parseRouter(); this.dispatch(this.actions.putRouteData({showComment: true})); return result; } @effect() protected async [ModuleNames.photos + "/INIT"]() { await super.onInit(); }}
差异示例:在 Dva 中,因为使用 redux-saga,假设在一个 effect 中使用 yield put 派发一个 action,以此来调用另一个 effect,虽然 yield 可以等待 action 的派发,但并不能等待后续 effect 的处理:
// 在Dva中,updateState并不会等待otherModule/query的effect处理完毕了才执行effects: {    * query (){        yield put({type: 'otherModule/query',payload:1});        yield put({type: 'updateState',  payload: 2});    }}// 在本框架中,可使用awiat关键字, updateState 会等待otherModule/query的effect处理完毕了才执行class ModuleHandlers {    async query (){        await this.dispatch(otherModule.actions.query(1));        this.dispatch(thisModule.actions.updateState(2));    }}
差异示例:如果 ModuleA 进行某项操作成功之后,ModuleB 或 ModuleC 都需要 update 自已的 State,由于缺少 action 的观察者模式,所以只能将 ModuleB 或 ModuleC 的刷新动作写死在 ModuleA 中:
// 在Dva中需要主动Put调用ModuleB或ModuleC的Actioneffects: {    * update (){        ...        if(callbackModuleName==="ModuleB"){          yield put({type: 'ModuleB/update',payload:1});        }else if(callbackModuleName==="ModuleC"){          yield put({type: 'ModuleC/update',payload:1});        }    }}// 在本框架中,可使用ActionHandler观察者模式:class ModuleB {    //在ModuleB中兼听"ModuleA/update" action    async ["ModuleA/update"] (){        ....    }}class ModuleC {    //在ModuleC中兼听"ModuleA/update" action    async ["ModuleA/update"] (){        ....    }}

遵循规则:

  • M 和 V 之间使用单向数据流
  • 整站保持单个 Store
  • Store 为 Immutability 不可变数据
  • 改变 Store 数据,必须通过 Reducer
  • 调用 Reducer 必须通过显式的 dispatch Action
  • Reducer 必须为 pure function 纯函数
  • 有副作用的行为,全部放到 Effect 函数中
  • 每个 reducer 只能修改 Store 下的某个节点,但可以读取所有节点
  • 路由组件化,不使用集中式配置

快速上手及 Demo

本框架上手简单

  • 8 个新概念:

    Effect、ActionHandler、Module、ModuleState、RootState、Model、View、Component
  • 4 步创建:

    exportModel(), exportView(), exportModule(), createApp()
  • 3 个 Demo,循序渐进:

转载地址:http://erweo.baihongyu.com/

你可能感兴趣的文章
我的友情链接
查看>>
兼容IE,Firefox,CSS3 opacity透明度
查看>>
读取Hive中所有表的表结构,并在新Hive库中创建表,索引等
查看>>
XenServer部署系列之02——系统安装及许可
查看>>
linux下FTP服务器搭建
查看>>
程序的查询 ps - 笔记1
查看>>
Conversion to Dalvik format failed with error 1的又一种情形
查看>>
nodejs抓取数据二(列表解析)
查看>>
TextView中实现可点击链接的显示
查看>>
HAOI 树上操作
查看>>
深刻理解Python中的元类(metaclass)以及元类实现单例模式
查看>>
java随机生成n个不相同的整数
查看>>
DIV+CSS基础
查看>>
使用JS完成首页定时弹出广告图片
查看>>
codeforces 500c New Year Book Reading 【思维】
查看>>
Auto reloading enabled
查看>>
GitHub的使用方法
查看>>
AT3576 Popping Balls
查看>>
springboot入门_多数据源
查看>>
如果一个游戏上面加一个透明层,js能不能实现 点击透明层的任意点 而正常玩游戏...
查看>>