Mobx在React中的應用

一、環境安裝

1、首先使用 npm install mobx mobx-react 安裝mobx和mobx-react
2、開通實驗權限:experimentalDecorators: 解決辦法:在項目根目錄下創建一個jsconfig.json文件,然後加上
{
    "compilerOptions": {
        "experimentalDecorators": true
    }
}

3、解決Support for the experimental syntax 'decorators-legacy' isn't currently enabled (5:5): 報錯。
第一步: 安裝decorators:  npm install @babel/plugin-proposal-decorators;
第二步:在package.json中加入這句話:
"babel": {
    "plugins":[[
      "@babel/plugin-proposal-decorators",{
        "legacy":true
      }
    ]],
    "presets": [
      "react-app"
    ]
  }

二、Mobx的基礎知識

mobx是使用狀態管理庫。建議大家看一下此大神的基礎視頻,有利於本文的理解
[慕課](https://www.imooc.com/learn/1012)

中文官網地址:https://cn.mobx.js.org/refguide/action.html

先來一個例子(後面會有介紹):

import { observable, action, computed } from "mobx";

class Todo {
  @observable title = "";
  @observable finished = false;

  constructor(title) {
    this.title = title;
  }
  @action.bound changeState() {
    this.finished = !this.finished;
  }
}

class Store {
  @observable todos = [];

  /**
   *
   * @param {刪除} todo
   */
  @action.bound delete(todo) {
    this.todos.remove(todo);
  }

  /**
   * 得到非finished得長度
   */
  @computed get todoLength() {
    return this.todos.filter(value => !value.finished).length;
  }

  /**
   *
   * @param {添加一個todo} title
   */
  @action.bound addTodo(title) {
      
    this.todos.unshift(new Todo(title));
  }
}

export { Store, Todo };


Mobx的用法介紹:

  •  @observalbe:可以用來觀測一個數據,這個數據可以數字、字符串、數組、對象等類型;
  •  @action: 動作是任何用來修改狀態的東西。 action 裝飾器/函數遵循 javascript 中標準的綁定規則。 但是,action.bound 可以用來自動地將動作綁定到目標對象
  •  @computed: 當狀態發生變化時,自動得到一個計算值。
  •  @observer:可以觀察可觀察者的對象,可以接收到可觀察者發生變化時候發出的消息,並且根據變化做出響應;也就是當observalue修飾的數據變化之後,會自動觸發唄observer修飾的對象。

三、使用mobx顯示列表數據

現在我們有這樣一個需求,使用輸入框,每次輸入數據之後,按一下enter鍵,就在列表中添加一條數據,並且在底部顯示出沒有被選中的條目。點擊每一項的刪除鍵時候刪除數據。同時更新頭部,底部,和列表。

因爲在一個項中刪除會同步修改header,footer以及列表顯示。那麼久需要使用到Mobx的另一個特性:observer 用來說明哪些對象需要監聽observable修飾的數據

效果圖:

效果圖

//先看整體
import React, { Component } from "react";
import { Store } from "./Store";
import { observer } from "mobx-react";
import "./index.css";

/**
 * 頭部負責輸入數據
 */

@observer
class HeaderInput extends Component {
 
}

/**
 * 底部負責顯示當前未選中數據的個數
 */
@observer
class Footer extends Component {
 
}

/**
 * 列表項目的每一個
 */
@observer
class TodoItem extends Component {
  
}

/**
 * 顯示整個列表
 */
@observer
class TodoView extends Component {
 
  
}

var store = new Store();

/**
 * 將列表,頭部,底部結合起來
 */
@observer
class MobxDemo extends Component {
  render() {
    return (
      <div>
        <HeaderInput store={store} />

        <TodoView store={store} />
        <Footer shift={store.todoLength} />
      </div>
    );
  }
}

export default MobxDemo;


上述代碼中使用mobx的observer特性,列表的顯示分爲頭部,列表顯示部分,底部。我們首先來看頭部的邏輯。

頭部的主要功能:在輸入框中輸入數據,當鍵盤按下enter的時候,觸發之前使用@action修飾的addTodo 動作,這樣狀態中的數據就會增加一條。

/**
 * 頭部負責輸入數據
 */

@observer
class HeaderInput extends Component {
  state = { inputValue: "" };

  /**
   * 提交
   */
  onSubmit = e => {
    e.preventDefault();
    //store是是在MobxDemo中傳入進來的,然後修改狀態中的值
    this.props.store.addTodo(this.state.inputValue);

    console.log(this.state.inputValue);
    //添加之後要清空輸入框的值
    this.setState({
      inputValue: ""
    });
  };

  /**
   * 監聽輸入框的輸入
   */
  onInputChange = e => {
    var inputValue = e.target.value;
    this.setState({
      inputValue
    });
  };

  render() {
    return (
      <div>
        <form className="header-form" onSubmit={this.onSubmit}>
          <input
            className="header-input"
            onChange={this.onInputChange}
            value={this.state.inputValue}
            placeholder="Please input ...."
          />
        </form>
      </div>
    );
  }
}

然後我們再來看底部,底部的主要功能就是顯示沒有finished的項個數。沒錯就是這樣簡單,但是要記得有observer哦

/**
 * 底部負責顯示當前未選中數據的個數
 */
@observer
class Footer extends Component {
  render() {
    return <div className="todo-footer">{this.props.shift + ", length"}</div>;
  }
}

然後我們可以來開始渲染列表咯,列表的渲染分爲 列表整體的渲染和每一項的渲染。

/**
 * 列表項目的每一個,有一個複選框,和title
 */
@observer
class TodoItem extends Component {
  onChangeState = () => {
    this.props.todo.changeState();
  };
  render() {
    var { title, finished } = this.props.todo;
    return (
      <div className="todo-item-d">
        <input
          type="checkbox"
          checked={finished}
          onChange={this.onChangeState}
        />
        <span className={["title", finished && "delete"].join(" ")}>
          {title}
        </span>
      </div>
    );
  }
}

/**
 * 顯示整個列表
 */
@observer
class TodoView extends Component {
  /**
   * 獲取隨機的顏色
   */
  getRandomColor = () => {
    return {
      backgroundColor: (function() {
        return "#" + Math.floor(Math.random() * 0xffffff).toString(16);
      })()
    };
  };

  render() {
  //獲取到store中有哪些todo
    var store = this.props.store;
    var todos = store.todos;

    return todos.map((item, index) => {
      return (
        <li key={index} className="todo-item" style={this.getRandomColor()}>
          <TodoItem todo={item} />
       {/* 這是一個刪除按鈕,調用的是store中唄@action修飾過得刪除動作 */}
          <span
            className="delete-item"
            onClick={() => {
              store.delete(item);
            }}
          >
            X
          </span>
        </li>
      );
    });
  }
}

最後:本項目的github地址react與mobx集成實例 歡迎start!

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