摘要:結(jié)合編輯器可以推導(dǎo)變量對應(yīng)的類型以及內(nèi)部的結(jié)構(gòu),提高代碼的健壯性和可維護(hù)性。通過充分利用時(shí)間回溯的特征,可以增強(qiáng)業(yè)務(wù)的可預(yù)測性與錯(cuò)誤定位能力。對于對象的哪部分需要成為可觀察的,提供了細(xì)粒度的控制。
為什么要使用TypeScript 偵測錯(cuò)誤
通過靜態(tài)類型檢測可以盡早檢測出程序中隱藏的的邏輯錯(cuò)誤,對于JavaScript動(dòng)態(tài)的弱類型語言,雖然靈活性高,但是對于初學(xué)者來說,如果不熟悉JavaScript內(nèi)部的語言機(jī)制,很容易造成隱藏的事故。但是通過TypeScript的靜態(tài)類型檢測可以規(guī)避這些問題,因?yàn)槠淠軌蚣s束變量產(chǎn)生的類型。結(jié)合IDE編輯器可以推導(dǎo)變量對應(yīng)的類型以及內(nèi)部的結(jié)構(gòu),提高代碼的健壯性和可維護(hù)性。
抽象類型系統(tǒng)能夠強(qiáng)化規(guī)范編程,TypeScript提供定義接口。在開發(fā)大型復(fù)雜的應(yīng)用軟件時(shí)十分重要,一個(gè)系統(tǒng)模塊可以抽象的看做一個(gè)TypeScript定義的接口。讓設(shè)計(jì)脫離實(shí)現(xiàn),最終體現(xiàn)出一種 IDL(接口定義語言,Interface Define Language),讓程序設(shè)計(jì)回歸本質(zhì)。
文檔TypeScript可以自動(dòng)根據(jù)類型標(biāo)注生成文檔,對于簡單的功能實(shí)現(xiàn)都不需要編寫注釋。
為什么要使用Mobx MobX 和 Redux 的比較先要明白 mobx 和 redux 的定位是不同的。redux 管理的是 (STORE -> VIEW -> ACTION) 的整個(gè)閉環(huán),而 mobx 只關(guān)心 STORE -> VIEW 的部分。
Redux優(yōu)缺點(diǎn):
數(shù)據(jù)流流動(dòng)很自然,因?yàn)槿魏?dispatch 都會觸發(fā)廣播,依據(jù)對象引用是否變化來控制更新粒度。
通過充分利用時(shí)間回溯的特征,可以增強(qiáng)業(yè)務(wù)的可預(yù)測性與錯(cuò)誤定位能力。
時(shí)間回溯代價(jià)高,因?yàn)槊看味家乱茫窃黾哟a復(fù)雜度,或使用 immutable。
時(shí)間回溯的另一個(gè)代價(jià)是 action 與 reducer 完全脫節(jié),原因是可回溯必然不能保證引用關(guān)系。
引入中間件,解決異步帶來的副作用,業(yè)務(wù)邏輯或多或少參雜著 magic。
靈活利用中間件,可以通過約定完成許多復(fù)雜的工作。
對 typescript 支持困難。
Mobx優(yōu)缺點(diǎn):
數(shù)據(jù)流流動(dòng)不自然,只有用到的數(shù)據(jù)才會引發(fā)綁定,局部精確更新,但避免了粒度控制煩惱。
沒有時(shí)間回溯能力,因?yàn)閿?shù)據(jù)只有一份引用。自始至終一份引用,不需要 immutable,也沒有復(fù)制對象的額外開銷。
數(shù)據(jù)流動(dòng)由函數(shù)調(diào)用一氣呵成,便于調(diào)試。
業(yè)務(wù)開發(fā)不是腦力活,而是體力活,少一些 magic,多一些效率。
由于沒有 magic,所以沒有中間件機(jī)制,沒法通過 magic 加快工作效率(這里 magic 是指 action 分發(fā)到 reducer 的過程)。
完美支持 typescript。
SO: 前端數(shù)據(jù)流不太復(fù)雜的情況,使用 Mobx,因?yàn)楦忧逦脖阌诰S護(hù);如果前端數(shù)據(jù)流極度復(fù)雜,建議謹(jǐn)慎使用 Redux,通過中間件減緩巨大業(yè)務(wù)復(fù)雜度
使用Create-React-App來建立TypeScript的環(huán)境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: 最后一個(gè)命令使用eject將所有內(nèi)建的配置暴露出來
通過create-react-app可以很方便地對整個(gè)項(xiàng)目完成環(huán)境初始化,如果愿意折騰TypeScript和webpack的環(huán)境可以試試,這里忽略webpack和TypeScript的環(huán)境搭建過程,而是使用create-react-app來實(shí)現(xiàn)環(huán)境搭建。
加入React-Router單頁應(yīng)用怎么可以沒有前端路由呢,所以我們要加入React-Rotuer, 這里使用的React-Router的版本是v4.2.0
路由配置使用姿勢對于React-Router,這里使用到的模塊有Router, Route, Switch
React Router 是建立在 history 之上的。 簡而言之,一個(gè) history 知道如何去監(jiān)聽瀏覽器地址欄的變化, 并解析這個(gè) URL 轉(zhuǎn)化為 location 對象, 然后 router 使用它匹配到路由,最后正確地渲染對應(yīng)的組件。
代碼如下:
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(頁面的編寫, document.getElementById("root") as HTMLElement ); registerServiceWorker();
這里描述一寫Container這個(gè)組件的編寫
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"; // 這部分是坑點(diǎn),一開始不知道配置,后發(fā)現(xiàn)react-rotuer的4.0版本下需要配置prop的接口 interface Container extends RouteComponentProps<{}> { } class Container extends React.Component{ render () { return ( ) } } export default Container;
這樣,當(dāng)我們訪問url為"/"的時(shí)候,默認(rèn)會進(jìn)入Container,其中Container里面是一層子頁面,會匹配url,如果url為"/website", 則進(jìn)入Website頁面,若為"/",則進(jìn)入App頁面。
具體關(guān)于React-Router的使用請閱讀React-Router文檔
加入Mobxnpm 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來進(jìn)行數(shù)據(jù)狀態(tài)的管理 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的嚴(yán)格模式,規(guī)范數(shù)據(jù)修改操作只能在action中進(jìn)行 useStrict(true); const browserHistory = createBrowserHistory(); const routerStore = new RouterStore(); // 同步路由與mobx的數(shù)據(jù)狀態(tài) 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(Container容器的修改, document.getElementById("root") as HTMLElement ); registerServiceWorker();
import * as React from "react"; import Header from "../../layout/Header"; import { IAuth } from "../../interfaces"; import { Route, Switch } from "react-router"; // 使用inject和observer來進(jìn)行數(shù)據(jù)監(jiān)聽和數(shù)據(jù)依賴聲明 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{ render () { return ( ) } } export default Container;
@observable 可以在實(shí)例字段和屬性 getter 上使用。 對于對象的哪部分需要成為可觀察的,@observable 提供了細(xì)粒度的控制。組件的接口定義@inject 相當(dāng)于Provider 的高階組件。可以用來從 React 的context中挑選 store 作為 prop 傳遞給目標(biāo)組件
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"; // 路由狀態(tài)同步 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"; // 登錄注冊狀態(tài) 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是用于網(wǎng)站的登錄注冊事件以及對應(yīng)的Token的數(shù)據(jù)狀態(tài)保存,登錄注冊事件的接口請求等操作。
具體的有關(guān)Mobx的用法請閱讀Mobx文檔
目錄結(jié)構(gòu)app ├── api 后端提供的接口數(shù)據(jù)請求 ├── components 編寫的可復(fù)用組件 ├── config 側(cè)邊欄以及導(dǎo)航欄配置 ├── constants 常量編寫 ├── interfaces 接口編寫 ├── layout 布局外框 ├── stores mobx的數(shù)據(jù)狀態(tài)管理 ├── index.css 全局樣式 ├── index.tsx 頁面入口 ├── reset.css 瀏覽器重置樣式
本項(xiàng)目使用了Ant-Design來作為依賴的組件庫,具體怎么使用以及配置請參考Ant-Design
到這里其實(shí)以及完成對React下TypeScript結(jié)合React-Router和Mobx的配置。具體的業(yè)務(wù)模塊如何編寫有興趣可以參閱項(xiàng)目tinylog-ui
個(gè)人表達(dá)能力有限,無法描述得太清晰,請見諒!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/95221.html
摘要:現(xiàn)已存在許多成熟的狀態(tài)管理解決方案,還有基于的但對于我個(gè)人來說,理想的狀態(tài)管理工具只需同時(shí)滿足兩個(gè)特點(diǎn)簡單易用,并且適合中大型項(xiàng)目完美地支持要做到這兩點(diǎn)其實(shí)并不簡單。所以我決定自己造一個(gè)可能是基于和最好的狀態(tài)管理工具 現(xiàn)已存在許多成熟的狀態(tài)管理解決方案:Redux、Mobx、Mobx-state-tree,還有基于 Redux 的 Dva.js、Rematch... 但對于我個(gè)人來說,...
摘要:的另一個(gè)核心特性,蘋果表示也正在開發(fā)中,按開發(fā)進(jìn)度可能幾個(gè)月后就能與我們見面。是基于的本地化數(shù)據(jù)庫,支持以及瀏覽器環(huán)境。 前端每周清單專注前端領(lǐng)域內(nèi)容,以對外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點(diǎn);分為新聞熱點(diǎn)、開發(fā)教程、工程實(shí)踐、深度閱讀、開源項(xiàng)目、巔峰人生等欄目。歡迎關(guān)注【前端之巔】微信公眾號(ID: frontshow),及時(shí)獲取前端每周清單。 本期是 2017 年的最后一...
摘要:通過裝飾器或者利用時(shí)調(diào)用的函數(shù)來進(jìn)行使用下面代碼中當(dāng)或者發(fā)生變化時(shí),會監(jiān)聽數(shù)據(jù)變化確保通過觸發(fā)方法自動(dòng)更新。只能影響正在運(yùn)行的函數(shù),而無法影響當(dāng)前函數(shù)調(diào)用的異步操作參考官方文檔用法裝飾器函數(shù)遵循中標(biāo)準(zhǔn)的綁定規(guī)則。 前言: 本文基于React+TypeScript+Mobx+AntDesignMobile技術(shù)棧,使用Create-React-App腳手架進(jìn)行一個(gè)移動(dòng)端項(xiàng)目搭建,主要介紹項(xiàng)...
摘要:發(fā)布發(fā)布節(jié)奏變化從月份的開始,將每周發(fā)布一個(gè)新的穩(wěn)定版本。將于年月日開始測試,穩(wěn)定版將于年月日發(fā)布。一個(gè)使用和實(shí)現(xiàn)了個(gè)用戶界面的頁面。實(shí)踐總結(jié)是一個(gè)現(xiàn)代的企業(yè)級框架,提供了強(qiáng)大的和許多開箱即用的功能。 .markdown-body{word-break:break-word;line-height:1.75;font-weight:400;font-size:15px;overflow-x...
摘要:年前公司由一個(gè)項(xiàng)目是使用來開發(fā)的所以遇到了一些問題比較影響開發(fā)進(jìn)程的就是路由問題了實(shí)際上就是這個(gè)組件比較難懂這里給大家講解一下希望大家少踩點(diǎn)坑另外本篇文章使用的是環(huán)境主要講解的還是如何使用記錄中路由的狀態(tài)但是會穿插一些小內(nèi)容這里雖然講到的是 年前公司由一個(gè)項(xiàng)目是使用 ReactNative 來開發(fā)的所以遇到了一些問題,比較影響開發(fā)進(jìn)程的就是路由問題了,實(shí)際上就是 ReactNaviga...
閱讀 1659·2021-11-23 10:07
閱讀 2652·2019-08-30 11:10
閱讀 2834·2019-08-29 17:08
閱讀 1778·2019-08-29 15:42
閱讀 3163·2019-08-29 12:57
閱讀 2396·2019-08-28 18:06
閱讀 3544·2019-08-27 10:56
閱讀 382·2019-08-26 11:33