MobX - Mobx會對什麼反應?

MobX會對在任何一個被監控的function執行的過程當中被讀取的已經存在的observable的屬性進行反應。
上面的這句話裏面有幾個關鍵的點:
1:正在被讀取
正在讀取的意思是:取用一個對象的屬性。例如:user.name或者user['name']
2:可被監控的function
可被監控的function是computed的一個表述,有如下幾種狀況:react

1:一個observer的組件的render()方法
2:做爲第一個參數傳給when(), reaction()和autorun()的function

3:在...過程當中
在...過程當中,意思是隻有在方法的執行中被讀取的observable才被track了。這些observable是被直接的仍是間接地被使用,並不影響。數組

換句話說,MboX不會對如下狀況進行反應:
1:從一個observable讀取的值,可是沒有被用在一個可被監控的function裏面
2:在一個異步調用的代碼塊裏被讀取的變量異步

一:MobX監控屬性的讀取,而不是屬性的值
咱們如下面的一段代碼示例來解釋上面的這條規則是設麼意思:spa

let message = observable({
    title: "Foo",
    author: {
        name: "Michel"
    },
    likes: ["John", "Sara"]
})

在內存裏面它看起來以下圖所示。綠色的模塊表示是observable的屬性。注意,這些數值自己不是observable的!
Screen Shot 2019-11-15 at 7.23.26 PM.pngcode

如今基本上,MobX作的事情就是記錄在你的function裏面,你使用的是哪一個箭頭。在那以後,不論哪一個箭頭髮生變化,他都會從新運行。也就是當這些箭頭指向一個其餘的值。server

Examples
咱們基於上面的message這個observable。對象

正確:在一個被監控的方法裏面讀取一個屬性:blog

autorun(()=>{
  console.log(message.title)
})
message.title = 'Bar'

以上代碼會如咱們期待的那樣。由於.title是在autorun裏面被讀取,且以後改變了,因此這個改變會被識別到。內存

不正確:修改一個不是observable的referenceit

autorun(() => {
    console.log(message.title)
})
message = observable({ title: "Bar" })

上面的代碼不會反應。由於雖然message改變了,可是message不是一個observable,而僅僅是一個指向一個observable的變量,而這個變量(這個reference)它本身不是一個observable。

不正確:在一個監控方法外讀取屬性

var title = message.title
autorun(() => {
    console.log(title)
})
message.title = "Bar"

這段代碼也不會反應,由於message.title是在監控方法外被讀取,於是它只是包含message.title的值(也就是'Foo')。因此,title不是一個observable,因此autorun不會反應。

正確: 在一個監控方法內部讀取屬性

autorun(() => {
    console.log(message.author.name)
})
message.author.name = "Sara"
message.author = { name: "John" }

以上代碼的最後2行代碼都會致使MboX反應。由於.author和.author.name都在一個autorun裏面被引用,這就容許MboX去跟蹤這些references。

不正確:給一個observable存儲了一個沒有被跟蹤的本地變量

const author = message.author
autorun(() => {
    console.log(author.name)
})
message.author.name = "Sara"
message.author = { name: "John" }

上面的代碼,倒數第一行不會觸發MobX反應,而倒數第二行會。由於,在autorun裏面只獲取了author.name,而message.author沒有在autorun裏面被使用,因此message.author的變化沒有被跟蹤,在autorun裏面使用的仍是老的author。

接下來咱們要看Array了。Array的狀況與Object有一些區別。
如下的例子,依然基於如下的代碼:

let message = observable({
    title: "Foo",
    author: {
        name: "Michel"
    },
    likes: ["John", "Sara"]
})

正確:在一個被監控的方法裏讀取Array的屬性

autorun(() => {
    console.log(message.likes.length)
})
message.likes.push("Jennifer")

以上的代碼會按照咱們期待的那樣執行。.length是Array的一個屬性。注意:上面的代碼會對array的任何改變都做出反應。Array是檢測它的所有,而不是像map或者對象那樣監控每個鍵值對。例如:

autorun(() => {
    console.log(message.likes[0])
})
message.likes.push("Jennifer")

以上的這段代碼,新增長了一個元素,使得Array自己改變了,因此會致使autorun裏面的代碼會被從新執行一遍。Array的下標被當作屬性被訪問,可是隻有當下標沒有越界的狀況下才有效。Mobx不會監控還不存在的下標或者對象的屬性(除非是用map)。

不正確:在被監控的方法裏訪問越界的元素

autorun(() => {
    console.log(message.likes.join(", "))
})
message.likes[2] = "Jennifer"

以上的代碼不會成功。由於訪問了越界的下標。

正確: 在監控方法裏面訪問Array的方法

autorun(() => {
    console.log(message.likes.join(", "))
})
message.likes.push("Jennifer")

以上代碼會按照指望的觸發autorun的執行。Array全部的沒有修改原Array的方法,都會被自動監控。

不正確:使用了observable,可是沒有讀取它的任何屬性

autorun(() => {
    message.likes
})
message.likes.push("Jennifer")

以上的代碼不會使得autorun在執行。由於,likes數組本身自己沒有被autorun使用,而是likes數組的reference被autorun使用了。

相關文章
相關標籤/搜索