React+TypeScript+Mobx+AntDesignMobile進行移動端項目搭建

前言:

本文基於React+TypeScript+Mobx+AntDesignMobile技術棧,使用Create-React-App腳手架進行一個移動端項目搭建,主要介紹項目搭建過程和相關配置,以及狀態管理工具Mobx的使用,最後實現點擊按鈕數字+1和一個簡單的TodoList小功能,希望能對大家有所幫助。GitHub代碼地址

項目搭建具體步驟:

  • 安裝Create-React-App腳手架工具,已經安裝的同學請忽略

    npm install create-react-app -g

  • 創建初始項目
    create-react-app my-app --typescript

    注意:
    如果同學你是參考typescript官方文檔進行react項目搭建,裏面有用create-react-app my-app --scripts-version=react-scripts-ts命令創建的,千萬別用,現在已經過時了,
    webpack版本有問題,後續配置各種想不到的坑 TypeScript中文官網

  • 引入AntDesignMobile,實現組件按需加載

    本步驟官網有比較詳細的介紹,我就不一一列舉配置過程了,建議大家不要eject暴露所有內建配置,後續版本升級維護可能比較麻煩,推薦使用 react-app-rewired 插件即可配置;AntDesignMobile官網
  • 安裝React路由,狀態管理工具mobx,配置sass

        npm install history @types/history react-router-dom @types/react-router-dom // 安裝react路由
        npm install mobx-react mobx  // 安裝mobx
        npm install node-sass // 安裝sass工具,安裝之後無需另外配置sass,腳手架工具已經集成了
        
  • 基本配置完成,運行項目
    npm run start

React狀態管理工具Mobx介紹:

Mobx是一個功能強大,基於面向對象編程方式的一個狀態管理工具,上手相對比較容易。就連Redux的作者也曾經向大家推薦過它,對TypeScript支持比較友好,參考官網一張流程圖:
Mobx中文官網
圖片描述


下面介紹幾個Mobx核心概念

Observable state(可觀察的狀態)
MobX 爲現有的數據結構(如對象,數組和類實例)添加了可觀察的功能。 通過使用 @observable 裝飾器(ES.Next)來給你的類屬性添加註解就可以簡單地完成這一切。
import { observable } from "mobx";
class Todo {
    id = Math.random();
    @observable title = "";
    @observable finished = false;
}
Computed values(計算值)
使用 MobX, 你可以定義在相關數據發生變化時自動更新的值。 通過@computed 裝飾器或者利用 (extend)Observable 時調用 的getter / setter 函數來進行使用,下面代碼中當queue或者refresh發生變化時,MobX會監聽數據變化確保,通過Computed觸發fooProps方法自動更新。
import React from 'react';
import {observable, isArrayLike, computed, action, autorun, when, reaction,runInAction} from "mobx";
import {observer} from 'mobx-react';

// 定義數據Store
class Store {
    @observable queue:number = 1;
    @action refresh = ():void => {
        this.queue += 1;
        console.log('this.queue -> ', this.queue);
    }
    @computed get fooProps():any {
        return {
            queue: this.queue,
            refresh: this.refresh
        };
    }
  }
Actions(動作)
任何應用都有動作。動作是任何用來修改狀態的東西,mobx推薦將修改被觀測變量的行爲放在action中。action只能影響正在運行的函數,而無法影響當前函數調用的異步操作,參考官方文檔用法:
action(fn)
action(name, fn)
@action classMethod() {}
@action(name) classMethod () {}
@action boundClassMethod = (args) => { body }
@action(name) boundClassMethod = (args) => { body }
@action.bound classMethod() {}
action 裝飾器/函數遵循 javascript 中標準的綁定規則。 但是,action.bound 可以用來自動地將動作綁定到目標對象。 注意,與 action 不同的是,(@)action.bound 不需要一個name參數,名稱將始終基於動作綁定的屬性。
class Ticker {
    @observable tick = 0

    @action.bound
    increment() {
        this.tick++ // 'this' 永遠都是正確的
    }
}

const ticker = new Ticker()
setInterval(ticker.increment, 1000)

利用Mobx作爲狀態管理,實現兩個小功能

點擊按鈕+1
import React from 'react';
import {observable, isArrayLike, computed, action, autorun, when, reaction,runInAction} from "mobx";
import {observer} from 'mobx-react';
import {Button} from 'antd-mobile';
import './index.scss';

// 定義數據Store,用Mobx作爲狀態管理工具
class Store {
    @observable queue:number = 1;
    @action refresh = ():void => {
        this.queue += 1;
        console.log('this.queue -> ', this.queue);
    }
    @computed get fooProps():any {
        return {
            queue: this.queue,
            refresh: this.refresh
        };
    }
  }
// ts組件接收父組件傳遞過來的數據必須定義接口類型,否則報錯
interface BarProps{
    queue :number
}
// @observer修飾類,Bar組件接受Foo組建傳過來的queue屬性
@observer 
class Bar extends React.Component<BarProps>{
    render() {
        const {queue} = this.props
        return (
            <div className="queue">{queue}</div>
        )
    }
}
interface FooProps {
    queue: number,
    refresh():void
}
// Foo組件接收來自Add組件的store數據
@observer
class Foo extends React.Component<FooProps>{
    render() {
        const {queue,refresh} = this.props;
        return (
            <div>
                <Button type="primary" onClick = {refresh}>Refresh</Button>
                <Bar queue = {queue} />
            </div>
        )
    }
}
// 初始化store數據,傳遞給Foo組件
const store = new Store();
class Add extends React.Component{
    render() {
        return (
            <div>
                <h2 className="add"> hello react-ts-mobx</h2>
                <Foo queue = {store.queue} refresh = {store.refresh} />
            </div>
           
        )
    }
}
export default observer(Add)
TodoList功能
import React from 'react';
import {observable, isArrayLike, computed, action, autorun, when, reaction,runInAction} from "mobx";
import {observer} from 'mobx-react';
import './index.scss';
// 定義Todo數據類型
class Todo {
    id:number = new Date().getTime();
    title:string = '';
    finished:boolean = false;
    constructor(title:string) {
        this.title = title;
    }
}
// Store數據方法管理
class Store {
    @observable title:string = '';
    @observable todos:Todo[] =[];
    // 添加Todo的Title
    @action createTitle (e:any) {
        console.log('e',e.target.value);
        this.title = e.target.value;
    }
    // 增加Todo數據
    @action createTodo = () => {
        this.todos.unshift(new Todo(this.title));
        this.title = '';
    }
    // 刪除Todo
    @action delTodo (id:number) {
        this.todos.forEach((item,index) => {
            if (item.id === id) {
                this.todos.splice(index,1)
            }
        })
    }
    // 監聽todos數據變化,顯示剩餘待辦數量
    @computed get unfinished () {
        return this.todos.filter(todo => !todo.finished).length;
    }

}
interface TodoItemProps {
    todo:any;
    store:any;
}
// 每一條Todo數據組件
@observer 
class TodoItem extends React.Component<TodoItemProps> {
    render() {
        const {todo,store} = this.props
        return (
            <div className="item">
               <span>{todo.title}</span>
               <span onClick={()=> store.delTodo(todo.id)}>X</span>
            </div>
        )
    }
}
const store = new Store();
@observer 
class TodoList extends React.Component {
    render() {
        return (
            <div>
                <h2>TodoList</h2>
                <header>
                    <input type="text" placeholder="please input" value={store.title} onChange = {e => store.createTitle(e)} />
                    <button onClick ={store.createTodo}>add</button>
                </header>
                <ul>
                    {store.todos.map((todo)=>{
                        return <li key={todo.id}>
                           <TodoItem todo={todo} store = {store}/>
                        </li>
                    })}
                </ul>
                <footer>
                 {store.unfinished} item(s) unfinished
                </footer>
            </div>
        )
    }
}
export default TodoList

總結:

本人剛接觸TypeScript和Mobx不久,總結學習方法:應該先熟悉一些基本概念後,慢慢的做一些小功能,遇到問題認真思考後再查資料或者請教別人,反覆看文檔,加強對知識的理解;歡迎大佬們留言交流;GitHub代碼地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章