mobx

来源:http://www.cnblogs.com/miaowwwww/archive/2016/12/15/6184556.html
-Advertisement-
Play Games

原文地址:https://mobxjs.github.io/mobx/getting-started.html 寫在前面:本人英語水平有限,主要是寫給自己看的,若有哪位同學看到了有問題的地方,請為我指出,非常感謝; mobx是一個比redux更好的狀態管理包,代碼量更少,思路更清晰,沒有像redux ...


原文地址:https://mobxjs.github.io/mobx/getting-started.html

寫在前面:本人英語水平有限,主要是寫給自己看的,若有哪位同學看到了有問題的地方,請為我指出,非常感謝;

mobx是一個比redux更好的狀態管理包,代碼量更少,思路更清晰,沒有像redux那樣複雜的reducer,action (ps: redux的作者也推薦mobx,某大大告訴我的,並沒有原話鏈接)

1.mobx 反應流程

 2.the core idea

  State 是每一個應用程式的核心部分,而使用一個不合規範的 State 則是讓你的應用充滿 bug 和失控的不二法門,或者就是局部變數環繞,讓你的 state 失去了同步。有很多框架試圖解決這個問題,比如使用不可變的 state,但是這樣以來又帶來了新的問題,比如數據必須規格化,完整性約束失效等等。並且它變得不可能使用強大的概念,如原型。

  MobX 讓整個事情又變簡單了:它不允許產生失控的 state。它的理念也很簡單:所有可以從 state 中派生的事物,都會自動的派生。

  從概念上講,Mobx會像Excel 表格一樣處理您的應用程式。

 

  • 首先,有一個 state,它可以是一個object,array,primitives等等任何組成你程式的部分。你可以把這個想象成你應用程式的“單元格”。
  • 然後就是 derivations,一般它是指可以從 state 中直接計算的來的結果。比如未完成的任務的數量,這個比較簡單,也可以稍複雜一些比如渲染你的任務顯示的html。它類似於你的應用程式中的“公式和圖表”。
  • Reactions 和 derivations 很像,主要的區別在於 reactions 並不產生數據結果,而是自動完成一些任務,一般是和 I/O 相關的。他們保證了 DOM 和 網路請求會自動適時地出發。
  • 最後是 actions。Actions 指的是所有會改變 state 的事情,MobX 保證所有 actions 都會有對應的 derivations 和 reactions 相伴,保證同步。

2.A simple todo store...

  理論說的夠多的了,看一個例子也許會更明白一些。我們從一個簡單的 todo 程式開始。

   為了原創性,讓我們從一個非常簡單的ToDoStore開始。下麵是一個非常直接的TodoStore,它維護著一個todos的集合。沒有MobX參與。

class TodoStore {
    todos = [];

    get completedTodosCount() {
        return this.todos.filter(
            todo => todo.completed === true
        ).length;
    }

    report() {
        if (this.todos.length === 0)
            return "<none>";
        return `Next todo: "${this.todos[0].task}". ` + 
            `Progress: ${this.completedTodosCount}/${this.todos.length}`; 
    }

    addTodo(task) {
        this.todos.push({ 
            task: task,
            completed: false,
            assignee: null
        });
    }
}

const todoStore = new TodoStore();
                        

  我們剛剛創建了一個帶有todos集合的todoStore實例。用一些對象填充todoStore。為了確保我們看到我們的更改的影響,我們在每次更改後調用todoStore.report並記錄它。

  請註意,報表有意總是只列印第一個任務。它使這個例子有點人工,但正如你將看到下麵它很好地演示了MobX的依賴關係跟蹤是動態的。

 ===》 

3.Becoming reactive

   到目前為止,這段代碼沒有什麼特別之處。但是如果我們可以不再手動調用 report 方法,只聲明我們希望在每次狀態更改時調用它?我們只需要在想要的地方修改這個 state,所有的彙報都自動來做。

   幸運的是,這正是MobX可以為你做的。自動執行完全取決於狀態的代碼。這樣我們的報表功能就會自動更新,就像電子錶格中的圖表一樣。為了實現這一點,TodoStore必須成為可觀察的(observable),以便MobX可以跟蹤所有正在進行的更改。讓我們改變類就足以實現它。

  同時,completedTodosCount 屬性應該被自動派生。通過使用@observable和@computed裝飾器,我們可以在對象上引入observable屬性:

class ObservableTodoStore {
    @observable todos = [];
    @observable pendingRequests = 0;

    constructor() {
        mobx.autorun(() => console.log(this.report));
    }

    @computed get completedTodosCount() {
        return this.todos.filter(
            todo => todo.completed === true
        ).length;
    }

    @computed get report() {
        if (this.todos.length === 0)
            return "<none>";
        return `Next todo: "${this.todos[0].task}". ` + 
            `Progress: ${this.completedTodosCount}/${this.todos.length}`; 
    }

    addTodo(task) {
        this.todos.push({ 
            task: task,
            completed: false,
            assignee: null
        });
    }
}


const observableTodoStore = new ObservableTodoStore();

 

   至此!我們將一些屬性標記為@observable,以指示MobX這些值可以隨時間改變。計算用@computed來裝飾,以識別這些可以從狀態導出。

   pendingRequests和assignee屬性到目前為止未使用,但將在本教程後面使用。為了簡潔,本頁上的所有示例都使用ES6,JSX和裝飾器。但不要擔心,所有的裝飾在MobX有一個ES5寫法。

  在構造函數中,我們創建了一個report()將其包裝在mobx.autorun()。mobx.autorun()創建一個運行一次的reaction,然後每當在函數內部使用的任何可觀察數據發生變化時,自動重新運行。因為report()用observable todos屬性,所以它會在適當時列印報表。這在下一個列表中演示。只需按下運行按鈕:

==>

   純函數,對吧?report自動列印了,同步並且沒有泄漏的中間值。如果你仔細查看運行結果的話,你會發現我們的第四句語句沒有產生輸出,因為我們修改了todos[1]的數據,而我們在report中指明的數據,並沒有todos[1]的變化而發生變化。而第五句話修改了todos[0]的數據則輸出了。這個例子很好的說明瞭,autorun不是簡單的監視了todos,而是精確到了具體的一項。

 4.Making React reactive

   Ok, so far we made a silly report reactive. Time to build a reactive user interface around this very same store. React components are (despite their name) not reactive out of the box. The @observer decorator from the mobx-react package fixes that by wrapping the React component render method in autorun, automatically keeping your components in sync with the state. That is conceptually not different from what we did with the report before.

   好了,到目前為止我們做了一個愚蠢的 report reactive。是時候用非常相似的store創建一個reactive了。React components(儘管他們的名字)沒有反應開箱。

  mobx-react包中的@observer裝飾器通過在mobx.autorun()包裝React組件的render()方法來實現,自動保持組件與狀態同步。這在概念上與我們以前的報告沒有什麼不同

   下麵的清單定義了幾個React組件。在那裡唯一屬於MobX的東西是@observer裝飾器。這足以確保每個組件在相關數據更改時單獨重新render。您不需要再調用setState,也不必瞭解如何使用需要配置的選擇器或更高級的組件來(subscribe :redux中有 )訂閱應用程式狀態的適當部分。基本上,所有組件都變得聰明。然而,它們是以愚蠢的,聲明性的方式定義的。

@observer
class TodoList extends React.Component {
  render() {
    const store = this.props.store; 
    return (
      <div>
        { store.report }
        <ul>
        { store.todos.map(
          (todo, idx) => <TodoView todo={ todo } key={ idx } />
        ) }
        </ul>
        { store.pendingRequests > 0 ? <marquee>Loading...</marquee> : null }
        <button onClick={ this.onNewTodo }>New Todo</button>
        <small> (double-click a todo to edit)</small>
        <RenderCounter />
      </div>
    );
  }

  onNewTodo = () => { 
    this.props.store.addTodo(prompt('Enter a new todo:','coffee plz')); 
  } 
}

@observer
class TodoView extends React.Component {
  render() {
    const todo = this.props.todo;
    return (
      <li onDoubleClick={ this.onRename }>
        <input 
          type='checkbox'
          checked={ todo.completed }
          onChange={ this.onToggleCompleted } 
        />
        { todo.task }
        { todo.assignee 
          ? <small>{ todo.assignee.name }</small> 
          : null
        }
        <RenderCounter />
      </li>
    ); 
  }

  onToggleCompleted = () => {
    const todo = this.props.todo;
    todo.completed = !todo.completed;
  }

  onRename = () => {
    const todo = this.props.todo;
    todo.task = prompt('Task name', todo.task) || todo.task; 
  } 
}

ReactDOM.render(
  <TodoList store={ observableTodoStore } />, 
  document.getElementById('reactjs-app')
);

  下一個清單很好地顯示,我們只需要改變我們的數據,而不做任何其他事情。 MobX將自動從存儲中的狀態重新導出和更新用戶界面的相關部分。

  運行結果:

 

5.Working with references

  到目前為止,我們已經創建了observable對象(原型對象和plain對象),數組和基元(primitives)。你可能想知道,在MobX中如何處理引用?我的state是否允許形成圖表?在上一個列表中,您可能已經註意到todos有一個assignee 屬性。讓我們給他們一些值,通過引入另一個“store”(它只是一個glorified數組)包含人,和分配給他們的任務。

   

 

  那麼問題來了,observableTodoStore.todos本來就是@observable的,奈何有要再增加一個呢?

   答:大概因為改變的時候方便?

 

  We now have two independent stores. One with people and one with todos. To assign an assignee to a person from the people store, we just assigned a reference. These changes will be picked up automatically by the TodoView. With MobX there is no need to normalize data first and to write selectors to make sure our components will be updated. In fact, it doesn't even matter where the data is stored. As long as objects are made observable, MobX will be able to track them. Real JavaScript references will just work. MobX will track them automatically if they are relevant for a derivation. To test that, just try changing your name in the next input box (make sure you have pressed the above Run code button first!).

  我們現在有兩個獨立的商店。一個人和一個todos。要從people store中分配一個person的代理,我們只需要分配了一個參考。這些更改將由TodoView自動選取。使用MobX,沒有必要首先規範化數據,並且編寫選擇器以確保我們的組件將被更新。事實上,數據存儲的位置甚至都不重要。只要對象是可觀察的,MobX將能夠跟蹤它們。真正的JavaScript引用將正常工作。 MobX將自動跟蹤它們,如果它們與派生相關。要測試,只需嘗試在下一個輸入框中更改您的名稱(確保您已經按上面的Run代碼按鈕!)。

   

 

 

6.Asynchronous actions

   因為我們的小Todo應用程式中的一切都是從狀態派生而來的,所以當狀態改變時它並不重要。這使得創建非同步操作真的很簡單。只需按下麵的按鈕(多次)來模擬非同步載入新的todo項:

   後面的代碼真的很簡單。我們從更新存儲屬性pendingRequests開始,讓UI反映當前的載入狀態。一旦載入完成,我們更新商店的todos並再次減少pendingRequests計數器。只需將此代碼段與早期的TodoList定義進行比較,即可瞭解如何使用pendingRequests屬性

 

7.Conclusion

   就這樣!沒有樣板。只是一些UI組件中的簡單的聲明性組件,形成我們的完整的UI。這些是完全地,反應性地從我們的state中得到。現在,您可以開始在自己的應用程式中使用mobx和mobx-react包。您到目前為止學到的東西的簡短摘要:

  • 使用@observable裝飾器或observable(obj or array)函數令對象可以被MobX追蹤。
  • @computed裝飾器可以用於創建可以從狀態自動導出其值的函數。
  • 使用autorun運行依賴於某個可觀察狀態的函數。這對log,網路請求等很有用.
  • 使用來自mobx-react包的@observer裝飾器,使您的React組件真正被動。他們將自動和有效地更新。即使用於具有大量數據的大型複雜應用程式。

   (我這裡是不行的)

  可以隨意使用上面的可編輯代碼塊玩一段時間,以獲得MobX對所有更改的反應的基本感覺。例如,您可以向報告函數添加一條日誌語句,以查看它被調用的時間。或者根本不顯示報告,看看它如何影響TodoList的呈現。或僅在特定情況下顯示...

 

8.MobX is not a state container

   人們經常使用MobX作為Redux的替代品。但請註意,MobX只是一個庫來解決技術問題,而不是一個架構或甚至狀態容器本身。在這個意義上,上面的例子是設計的,並且建議使用適當的工程實踐,如在方法中封裝邏輯,在商店或控制器等組織它們。或者,正如HackerNews上的某人所說:

  “MobX,它在其他地方被提到,但我不能不贊揚它。在MobX中編寫意味著使用控制器/調度程式/操作/管理程式或另一種形式的管理數據流返回到一個架構問題,您可以模式化您的應用程式的需要,而不是預設情況下需要的任何東西比一個Todo應用程式。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 如果你是一名建築工人, 現在要建一棟十幾層的樓房, 你會按照什麼樣的一個順序去建造呢? 正常來說, 肯定是先打地基, 然後在此基礎上, 建一層, 建第二層 ...... , 就現在中國的科技來說, 還沒有說, 可以先建頂層, 再打地基, 在建倒數第二層, 這樣一種隨心所欲的建造方法來實現吧. 說白了 ...
  • 通過 CSS3,我們能夠創建動畫,這可以在許多網頁中取代動畫圖片、Flash 動畫以及 JavaScript。 CSS3 動畫 CSS3 動畫 CSS3 @keyframes 規則 如需在 CSS3 中創建動畫,您需要學習 @keyframes 規則。 @keyframes 規則用於創建動畫。在 @ ...
  • 過程概述 瀏覽器查找功能變數名稱對應的 IP 地址; 瀏覽器根據 IP 地址與伺服器建立 socket 連接; 瀏覽器與伺服器通信: 瀏覽器請求,伺服器處理請求; 瀏覽器與伺服器斷開連接。 以下為詳細解析: 根據功能變數名稱查找 IP 地址 概念解釋 IP 地址:IP 協議為互聯網上的每一個網路和每一臺主機分配的一 ...
  • ▓▓▓▓▓▓ 大致介紹 接下來的這幾個博客是對前面所學知識的一個簡單的應用,來加深理解 ▓▓▓▓▓▓ 單行文本框 只介紹一個簡單的樣式:獲取和失去焦點改變樣式 基本結構: 在CSS中添加一個類為focus的樣式 然後為文本框添加獲取和失去焦點事件 效果: ▓▓▓▓▓▓ 多行文本框應用 1、高度變化 ...
  • 1.原生ajax get請求和post請求區別:黃色小三角 以get請求為例,輸出結果如下: 2.jquery中的ajax 列了常用的6個方法: 3.狀態說明 readystate: 0:請求未初始化,open未調用 1:伺服器連接已建立,open已經調用了 2:請求已接受,也就是接收到頭信息了 3 ...
  • 冒泡排序(Bubble Sort),是一種電腦科學領域的較簡單的排序演算法。 它重覆地走訪過要排序的數列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。走訪數列的工作是重覆地進行直到沒有再需要交換,也就是說該數列已經排序完成。 這個演算法的名字由來是因為越大的元素會經由交換慢慢“浮”到數列的頂 ...
  • jQuery就是用原生js寫出的框架集(Write less do more ) 1.需要註意的問題?(1).jQuery語法需要重新學習(2).jQuery需要註意版本之間的相容性 (3)不是越新的版本越好(要穩定)(4)jQuery一般有兩個版本(xxx.min.js和xxx.js) 區別就是去 ...
  • 今天做了兩個靜態html頁面,在瀏覽器中測試的時候,發現其中一個html頁面的頂部多出了些許空白,而另一個頁面顯示正常。在瀏覽器中進行了審查對比,發現有空白的那個頁面的head標簽裡面的元素全部跑到了body裡面,而且body中還多出了一個,當把這個東西刪除之後就正常了。然後又在編輯器中,對比了一下 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...