>웹 프론트엔드 >JS 튜토리얼 >React와 TypeScript 및 Mobx를 결합하는 단계에 대한 자세한 설명

React와 TypeScript 및 Mobx를 결합하는 단계에 대한 자세한 설명

php中世界最好的语言
php中世界最好的语言원래의
2018-05-24 10:53:207124검색

이번에는 React와 TypeScript 및 Mobx를 결합하는 단계에 대해 자세히 설명하겠습니다. React와 TypeScript 및 Mobx를 결합할 때 주의 사항은 무엇입니까?

React와 TypeScript 및 Mobx를 결합하는 단계에 대한 자세한 설명

TypeScript를 사용하는 이유

오류 감지

정적 유형 감지를 통해 프로그램의 숨겨진 논리 오류를 가능한 한 빨리 감지할 수 있습니다. JavaScript동적 약한 유형의 언어는 매우 유연하지만 가능합니다. 초보자에게는 적합하지 않습니다. JavaScript의 내부 언어 메커니즘에 익숙하지 않은 경우 숨겨진 사고가 발생하기 쉽습니다. 그러나 TypeScript의 정적 유형 감지를 통해 이러한 문제를 피할 수 있습니다. 변수 유형을 제한할 수 있기 때문입니다. IDEEditor와 결합하면 변수에 해당하는 유형과 내부 구조를 추론할 수 있어 코드의 견고성과 유지 관리성이 향상됩니다.

Abstraction

타입 시스템은 표준화된 프로그래밍을 강화할 수 있으며 TypeScript는 정의 인터페이스를 제공합니다. 크고 복잡한 응용 프로그램 소프트웨어를 개발할 때 시스템 모듈은 추상적으로 TypeScript에서 정의한 인터페이스로 간주할 수 있습니다. 디자인을 구현과 분리하고 최종적으로 IDL(인터페이스 정의 언어)을 반영하여 프로그래밍이 본질로 돌아갈 수 있도록 합니다.

Documentation

TypeScript는 유형 주석을 기반으로 문서를 자동으로 생성할 수 있으며 간단한 기능 구현을 위해 주석을 작성할 필요가 없습니다.

Mobx를 사용하는 이유

MobX와 Redux의 비교

우선, mobx와 redux의 포지셔닝이 다르다는 점을 이해해야 합니다. Redux는 (STORE -> VIEW -> ACTION)의 전체 폐쇄 루프를 관리하는 반면 mobx는 STORE -> VIEW 부분에만 관심을 갖습니다.

Redux의 장점과 단점:

  • 모든 디스패치가 브로드캐스트를 트리거하고 업데이트 세분성이 개체 참조 변경 여부에 따라 제어되기 때문에 데이터 흐름이 매우 자연스럽게 흐릅니다.

  • 시간 역추적 기능을 최대한 활용하면 비즈니스 예측 가능성과 오류 위치 파악 기능을 향상할 수 있습니다.

  • 코드 복잡성이 증가하거나 불변성을 사용하지 않는 한 참조를 매번 업데이트해야 하기 때문에 시간 역추적에는 비용이 많이 듭니다.

  • 역추적의 또 다른 비용은 액션과 리듀서가 완전히 분리되어 있기 때문입니다. 그 이유는 역추적은 반드시 참조 관계를 보장할 수 없기 때문입니다.

  • 는 비동기로 인한 부작용을 해결하기 위해 미들웨어를 도입했으며 비즈니스 로직은 어느 정도 마법과 혼합되어 있습니다.

  • 미들웨어를 유연하게 사용하면 계약을 통해 복잡한 여러 작업을 완료할 수 있습니다.

  • 타입스크립트 지원이 어렵습니다.

Mobx의 장점과 단점:

  • 데이터 흐름이 부자연스럽습니다. 사용된 데이터만 바인딩 및 로컬 정확한 업데이트를 트리거하지만 세부적인 제어 문제를 방지합니다.

  • 데이터에 참조가 하나만 있으므로 시간 되돌리기 기능이 없습니다. 전체적으로 하나의 참조, 불변이 필요하지 않으며 객체 복사에 대한 추가 오버헤드도 없습니다.

  • 함수 호출로 데이터 흐름이 한 번에 완료되므로 디버깅이 쉽습니다.

  • 사업 개발은 정신적인 일이 아니라 육체적인 일이며 마술은 덜하고 효율성은 높습니다.

  • 마법이 없기 때문에 미들웨어 메커니즘도 없고 마술을 통해 작업 효율을 높일 방법도 없습니다. (여기서 마술은 리듀서에 액션을 분배하는 과정을 말합니다.)

  • 타입스크립트를 완벽하게 지원합니다.

SO: 프런트엔드 데이터 흐름이 너무 복잡하지 않은 경우 Mobx를 사용하세요. 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으로 문의하세요.