首頁 >web前端 >js教程 >React結合TypeScript和Mobx步驟詳解

React結合TypeScript和Mobx步驟詳解

php中世界最好的语言
php中世界最好的语言原創
2018-05-24 10:53:207149瀏覽

這次帶給大家React結合TypeScript和Mobx步驟詳解,React結合TypeScript和Mobx的注意事項有哪些,下面就是實戰案例,一起來看一下。

React結合TypeScript和Mobx步驟詳解

為什麼要使用TypeScript

偵測錯誤

透過靜態型別偵測可以儘早偵測出程式中隱藏的的邏輯錯誤,對於JavaScript動態的弱型別語言,雖然彈性很高,但對於初學者來說,如果不熟悉JavaScript內部的語言機制,很容易造成隱藏的事故。但是透過TypeScript的靜態類型來偵測可以規避這些問題,因為其能夠約束變數產生的類型。結合IDE編輯器可以推導變數對應的類型以及內部的結構,提高程式碼的健全性和可維護性。

抽象

類型系統能夠強化規範編程,TypeScript提供定義介面。在開發大型複雜的應用軟體時十分重要,一個系統模組可以抽象的看做一個TypeScript定義的介面。讓設計脫離實現,最終體現出 IDL(介面定義語言,Interface Define Language),讓程式設計回歸本質。

文檔

TypeScript可以自動根據類型標註產生文檔,對於簡單的功能實作都不需要編寫註解。

為什麼要使用Mobx

MobX 和 Redux 的比較

先明白 mobx 和 redux 的定位是不同的。 redux 管理的是 (STORE -> VIEW -> ACTION) 的整個閉環,而 mobx 只關心 STORE -> VIEW 的部分。

Redux優缺點:

  • 資料流流動很自然,因為任何 dispatch 都會觸發廣播,而依據物件參考是否已變更來控制更新粒度。

  • 透過充分利用時間回溯的特徵,可以增強業務的可預測性與錯誤定位能力。

  • 時間回溯代價高,因為每次都要更新引用,除非增加程式碼複雜度,或使用 immutable。

  • 時間回溯的另一個代價是 action 與 reducer 完全脫節,原因是可回溯必然無法保證引用關係。

  • 引入中介軟體,解決非同步帶來的副作用,業務邏輯或多或少參雜著 magic。

  • 靈活利用中間件,可以透過約定完成許多複雜的工作。

  • 對 typescript 支援困難。

Mobx優缺點:

  • 資料流流動不自然,只有用到的資料才會引發綁定,局部精確更新,但避免了粒度控制煩惱。

  • 沒有時間回溯能力,因為資料只有一份參考。自始至終一份引用,不需要 immutable,也沒有複製物件的額外開銷。

  • 資料流由函數呼叫一氣呵成,方便調試。

  • 業務開發不是腦力活,而是體力活,少一些 magic,多一些效率。

  • 由於沒有 magic,所以沒有中間件機制,沒辦法透過 magic 加快工作效率(這裡 magic 是指 action 分發到 reducer 的過程)。

  • 完美支援 typescript。

SO: 前端資料流較不複雜的情況,使用Mobx,因為更加清晰,也便於維護;如果前端資料流極度複雜,建議謹慎使用Redux,透過中間件減緩巨大業務複雜度

使用Create-React-App來建立TypeScript的環境

npm i -g create-react-app
create-react-app tinylog-ui --scripts-version=react-scripts-ts
cd tinylog-ui/
npm start
npm run eject

TPS: 最後一個指令使用eject將所有內建的設定暴露出來

#透過create-react-app可以很方便地對整個專案完成環境初始化,如果願意折騰TypeScript和webpack的環境可以試試,這裡忽略webpack和TypeScript的環境搭建過程,而是使用create-react-app來實現環境搭建。

加入React-Router

单页应用怎么可以没有前端路由呢,所以我们要加入React-Rotuer, 这里使用的React-Router的版本是v4.2.0

路由配置使用姿势

对于React-Router,这里使用到的模块有Router, Route, Switch

React Router 是建立在 history 之上的。 简而言之,一个 history 知道如何去监听浏览器地址栏的变化, 并解析这个 URL 转化为 location 对象, 然后 router 使用它匹配到路由,最后正确地渲染对应的组件。

代码如下:

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Router, Route, Switch } from 'react-router';
import { createBrowserHistory } from 'history';
import registerServiceWorker from './registerServiceWorker';
import { Root } from './containers/Root';
import './index.css';
import Container from './containers/Container';
import SignIn from './containers/Auth/signIn';
import SignUp from './containers/Auth/signUp';
const history = createBrowserHistory();
ReactDOM.render(
  <root>
    <router>
      <switch>
        <route></route>
        <route></route>
        <route></route>
      </switch>
    </router>
  </root>,
  document.getElementById('root') as HTMLElement
);
registerServiceWorker();

页面的编写

这里描述一写Container这个组件的编写

import * as React from 'react';
import Header from '../../layout/Header';
import { IAuth } from '../../interfaces';
import { Route, Switch } from 'react-router';
import App from '../App';
import Website from '../Website';
// 这部分是坑点,一开始不知道配置,后发现react-rotuer的4.0版本下需要配置prop的接口
interface Container extends RouteComponentProps {
}
class Container extends React.Component<container> {
  render () {
    return (
      <p>
        <header></header>
        <switch>
          <route></route>
          <route></route>
        </switch>
      </p>
    )
  }
}
export default Container;</container>

这样,当我们访问url为'/'的时候,默认会进入Container,其中Container里面是一层子页面,会匹配url,如果url为'/website', 则进入Website页面,若为'/',则进入App页面。

具体关于React-Router的使用请阅读React-Router文档

加入Mobx

npm i mobx react-mobx mobx-react-router -S

重新修改index.tsx的入口配置

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Router, Route, Switch } from 'react-router';
import { createBrowserHistory } from 'history';
import { useStrict } from 'mobx';
import { Provider } from 'mobx-react';
import { RouterStore, syncHistoryWithStore } from 'mobx-react-router';
// 定义需要使用到的store来进行数据状态的管理
import { 
  TokenStore, 
  AuthStore, 
  HostStore, 
  OverViewStore,
  AssetsStore,
  CommonDataStore,
  PageStore,
  RealTimeStore  
} from './stores';
import registerServiceWorker from './registerServiceWorker';
import { Root } from './containers/Root';
import './index.css';
import Container from './containers/Container';
import SignIn from './containers/Auth/signIn';
import SignUp from './containers/Auth/signUp';
// 引入Echarts
import './macarons';
import 'echarts/map/js/world';
// 开启mobx的严格模式,规范数据修改操作只能在action中进行
useStrict(true);
const browserHistory = createBrowserHistory();
const routerStore =  new RouterStore();
// 同步路由与mobx的数据状态
const history = syncHistoryWithStore(browserHistory, routerStore);
const rootStore = {
  token: new TokenStore(),
  auth: new AuthStore(),
  host: new HostStore(),
  overview: new OverViewStore(),
  assets: new AssetsStore(),
  commmon: new CommonDataStore(),
  page: new PageStore(),
  realtime: new RealTimeStore(),
  router: routerStore
};
ReactDOM.render(
  <provider>
    <root>
      <router>
        <switch>
          <route></route>
          <route></route>
          <route></route>
        </switch>
      </router>
    </root>
  </provider>,
  document.getElementById('root') as HTMLElement
);
registerServiceWorker();

Container容器的修改

import * as React from 'react';
import Header from '../../layout/Header';
import { IAuth } from '../../interfaces';
import { Route, Switch } from 'react-router';
// 使用inject和observer来进行数据监听和数据依赖声明
import { inject, observer } from 'mobx-react';
import App from '../App';
import Website from '../Website';
interface Container extends IAuth {
}
@inject('router', 'auth')
@observer
class Container extends React.Component<container> {
  render () {
    return (
      <p>
        <header></header>
        <switch>
          <route></route>
          <route></route>
        </switch>
      </p>
    )
  }
}
export default Container;</container>
@observable 可以在实例字段和属性 getter 上使用。 对于对象的哪部分需要成为可观察的,@observable 提供了细粒度的控制。

@inject 相当于Provider 的高阶组件。可以用来从 React 的context中挑选 store 作为 prop 传递给目标组件

组件的接口定义

import { RouteComponentProps } from 'react-router';
import {
  RouterStore,
  AuthStore
} from '../stores';
export interface IBase extends RouteComponentProps {
  router: RouterStore;
}
export interface IAuth extends IBase {
  auth: AuthStore;
}

Store的配置

先看一下RouterStore:

import { History } from 'history';
import { RouterStore as BaseRouterStore, syncHistoryWithStore } from 'mobx-react-router';
// 路由状态同步
class RouterStore extends BaseRouterStore {
  public history;
  constructor(history?: History) {
    super();
    if (history) {
      this.history = syncHistoryWithStore(history, this);
    }
  }
}
export default RouterStore;

然后是AuthStore:

import { ISignIn, ISignUp } from './../interfaces/index';
import { observable, action } from 'mobx';
import api from '../api/auth'; 
import { IUser } from '../models';
// 登录注册状态
class AuthStore {
  @observable token;
  @observable id;
  @observable email;
  constructor () {
    this.id = '';
    this.token = '';
    this.email = '';
  }
  setLocalStorage ({ id, token, email }: IUser) {
    localStorage.setItem('id', id);
    localStorage.setItem('token', token);
    localStorage.setItem('email', email);
  }
  clearStorage () {
    localStorage.clear();
  }
  @action async signIn (data: ISignIn) {
    try {
      const { data: res } = await api.signIn(data);
      this.id = res.data.id;
      this.token = res.data.token;
      this.email = res.data.email;
      this.setLocalStorage({
        id: this.id,
        token: this.token,
        email: this.email
      });
      return res;
    } catch (error) {
      return error;
    }
  }
  
  @action async signUp (data: ISignUp) {
    try {
      const { data: res } = await api.signUp(data);
      this.id = res.data.id;
      this.token = res.data.token;
      this.email = res.data.email;
      this.setLocalStorage({
        id: this.id,
        token: this.token,
        email: this.email
      });
      return res;
    } catch (error) {
      return error;
    }
  }
  @action signOut () {
    this.id = '';
    this.token = '';
    this.email = '';
    this.clearStorage()
  }
}
export default AuthStore;

Auth是用于网站的登录注册事件以及对应的Token的数据状态保存,登录注册事件的接口请求等操作。

具体的有关Mobx的用法请阅读Mobx文档

目录结构

app
├── api             后端提供的接口数据请求
├── components      编写的可复用组件
├── config          侧边栏以及导航栏配置
├── constants       常量编写
├── interfaces      接口编写
├── layout          布局外框
├── stores          mobx的数据状态管理
├── index.css       全局样式
├── index.tsx       页面入口
├── reset.css       浏览器重置样式

本项目使用了Ant-Design来作为依赖的组件库,具体怎么使用以及配置请参考Ant-Design

到这里其实以及完成对React下TypeScript结合React-Router和Mobx的配置。具体的业务模块如何编写有兴趣可以参阅项目tinylog-ui

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

Chart.js轻量级图表库使用案例解析

centos搭建ghost博客步骤分享

以上是React結合TypeScript和Mobx步驟詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn