設定 {🚀}
MobX 根據您偏好的使用方法、想要支援的 JavaScript 引擎,以及是否希望 MobX 提示最佳實務,提供多種設定選項。大多數設定選項都可以使用 configure
方法來設定。
Proxy 支援
預設情況下,MobX 使用 Proxy 來使陣列和普通物件成為可觀察的。Proxy 提供最佳效能和跨環境最一致的行為。但是,如果您的目標環境不支援 Proxy,則必須停用 Proxy 支援。最值得注意的是,在目標環境是 Internet Explorer 或未使用 Hermes 引擎的 React Native 時,就是這種情況。
可以使用 configure
停用 Proxy 支援
import { configure } from "mobx"
configure({
useProxies: "never"
})
useProxies
設定可接受的值為
"always"
(預設值):MobX 預期僅在具有Proxy
支援 的環境中執行,如果沒有此類環境,它將會出錯。"never"
:不使用 Proxy,MobX 會退回到非 Proxy 的替代方案。這與所有 ES5 環境相容,但會導致各種 限制。"ifavailable"
(實驗性):如果 Proxy 可用,則會使用 Proxy,否則 MobX 會退回到非 Proxy 的替代方案。此模式的優點是 MobX 會嘗試發出警告,如果使用了在 ES5 環境中無法運作的 API 或語言功能,則在現代環境中遇到 ES5 限制時會觸發錯誤。
**注意:**在 MobX 6 之前,必須為較舊的引擎選擇 MobX 4,或為新的引擎選擇 MobX 5。但是,MobX 6 同時支援兩者,儘管在目標環境是較舊的 JavaScript 引擎時,需要某些 API(例如 Map)的 polyfill。Proxy 無法使用 polyfill。即使存在 polyfill,它們也不支援完整的規範,並且不適用於 MobX。不要使用它們。
沒有 Proxy 支援的限制
- 可觀察陣列不是真正的陣列,因此它們不會通過
Array.isArray()
檢查。實際的後果是,您通常需要先.slice()
陣列(以取得真實陣列的淺拷貝),再將其傳遞給第三方函式庫。例如,串接可觀察陣列無法按預期工作,因此請先.slice()
它們。 - 在建立後新增或刪除現有可觀察普通物件的屬性不會自動被擷取。如果您打算將物件用作基於索引的查找映射,換句話說,將其用作事物的動態集合,請改用可觀察的 Map。
即使未啟用 Proxy,也可以動態地將屬性新增到物件,並偵測它們的添加。這可以使用 集合工具 {🚀} 來實現。請確保使用 set
工具設定(新的)屬性,並使用 values
/ keys
或 entries
工具之一來迭代物件,而不是使用內建的 JavaScript 機制。但是,由於這很容易被遺忘,因此我們建議盡可能使用可觀察的 Map。
裝飾器支援
如需啟用實驗性裝飾器支援,請參閱 啟用裝飾器 {🚀} 章節。
程式碼檢查選項
為了幫助您採用 MobX 提倡的模式,即在動作、狀態和衍生之間進行嚴格區分,MobX 可以透過提示程式碼異味,在執行階段對您的程式碼模式進行 _「程式碼檢查」_。為了確保 MobX 盡可能嚴格,請採用以下設定並閱讀其說明
import { configure } from "mobx"
configure({
enforceActions: "always",
computedRequiresReaction: true,
reactionRequiresObservable: true,
observableRequiresReaction: true,
disableErrorBoundaries: true
})
在某些時候,您會發現這種程度的嚴格性可能會相當煩人。一旦您確定您(和您的同事)理解了 MobX 的心智模型,就可以停用這些規則來提高生產力。
此外,有時您會遇到必須抑制這些規則觸發的警告的情況(例如,透過將其包裝在 runInAction
中)。這沒關係,這些建議有一些很好的例外情況。不要對它們抱持基本教義派的態度。
請務必也嘗試我們的 eslint
插件。雖然有些問題可以靜態地發現,但有些問題只能在執行階段偵測到。該插件旨在補充這些規則,而不是取代它們。自動修復功能還可以幫助處理樣板程式碼。
enforceActions
_enforceActions_ 的目標是讓您不要忘記將事件處理程式包裝在 action
中。
可能的選項
"observed"
(預設值):在 _某處_ 被觀察到的所有狀態都需要透過動作來更改。這是預設值,也是在非簡單應用程式中建議的嚴格模式。"never"
:可以從任何地方更改狀態。"always"
:狀態始終需要透過動作來更改,實際上也包括建立。
"observed"
的好處是它允許您在動作之外建立可觀察物件,並自由修改它們,只要它們尚未在任何地方使用即可。
由於原則上狀態應該始終從某些事件處理程式建立,並且事件處理程式應該被包裝,因此 "always"
最能體現這一點。但是您可能不希望在單元測試中使用此模式。
在極少數情況下,如果您懶惰地建立可觀察物件,例如在計算屬性中,您可以使用 runInAction
將建立臨時包裝在動作中。
computedRequiresReaction: boolean
禁止從動作或反應之外直接存取任何未觀察到的計算值。這可以確保您不會以 MobX 不會快取它們的方式使用計算值。**預設值:`false`**。
在以下範例中,MobX 不會在第一個程式碼區塊中快取計算值,但會在第二個和第三個區塊中快取結果
class Clock {
seconds = 0
get milliseconds() {
console.log("computing")
return this.seconds * 1000
}
constructor() {
makeAutoObservable(this)
}
}
const clock = new Clock()
{
// This would compute twice, but is warned against by this flag.
console.log(clock.milliseconds)
console.log(clock.milliseconds)
}
{
runInAction(() => {
// Will compute only once.
console.log(clock.milliseconds)
console.log(clock.milliseconds)
})
}
{
autorun(() => {
// Will compute only once.
console.log(clock.milliseconds)
console.log(clock.milliseconds)
})
}
observableRequiresReaction: boolean
警告任何未觀察到的可觀察物件存取。如果您想檢查是否在沒有「MobX 上下文」的情況下使用可觀察物件,請使用此選項。這是一種很好的方法來查找任何遺漏的 `observer` 包裝器,例如在 React 元件中。但它也會找到遺漏的動作。**預設值:`false`**
configure({ observableRequiresReaction: true })
**注意:**在使用 `observer` 包裝的元件上使用 propTypes可能會觸發此規則的誤報。
reactionRequiresObservable: boolean
在建立反應(例如 `autorun`)時,如果沒有存取任何可觀察物件,則會發出警告。使用此選項來檢查是否不必要地使用 `observer` 包裝 React 元件、使用 `action` 包裝函式,或者查找您只是忘記使某些資料結構或屬性成為可觀察物件的情況。**預設值:`false`**
configure({ reactionRequiresObservable: true })
disableErrorBoundaries: 布林值
預設情況下,MobX 會捕捉並重新拋出程式碼中發生的例外,以確保一個反應中的例外不會阻止其他可能不相關的反應的排程執行。這表示例外不會傳播回原始導致程式碼,因此您將無法使用 try/catch 捕捉它們。
透過停用錯誤邊界,例外可以跳脫衍生。這可能會簡化除錯,但可能會使 MobX 以及您的應用程式處於無法恢復的損壞狀態。**預設值:false
**。
此選項非常適合單元測試,但請記住在每次測試後呼叫 _resetGlobalState
,例如在 jest 中使用 afterEach
。
import { _resetGlobalState, observable, autorun, configure } from "mobx"
configure({ disableErrorBoundaries: true })
test("Throw if age is negative", () => {
expect(() => {
const age = observable.box(10)
autorun(() => {
if (age.get() < 0) throw new Error("Age should not be negative")
})
age.set(-1)
}).toThrow("Age should not be negative")
})
afterEach(() => {
_resetGlobalState()
})
safeDescriptors: 布林值
MobX 會將某些欄位設定為**不可配置**或**不可寫入**,以防止您執行不支援或很可能會破壞程式碼的操作。然而,這也可能阻止您在測試中進行**監視/模擬/樁構建**。configure({ safeDescriptors: false })
會停用此安全措施,使所有內容都**可配置**且**可寫入**。請注意,它不會影響現有的可觀察物件,只會影響配置後建立的可觀察物件。**請謹慎使用**,並且僅在需要時才使用 - 不要在所有測試中全域關閉此功能,否則您可能會遇到誤判(程式碼損壞但測試通過)。**預設值:true
**。
configure({ safeDescriptors: false })
更多設定選項
isolateGlobalState: 布林值
當同一個環境中有多個 MobX 實例處於活動狀態時,隔離 MobX 的全域狀態。當您有一個使用 MobX 的封裝程式庫,與使用 MobX 的應用程式位於同一個頁面中時,這會很有用。當您從程式庫中呼叫 configure({ isolateGlobalState: true })
時,程式庫中的反應性將保持自包含。
如果沒有這個選項,如果多個 MobX 實例處於活動狀態,它們的內部狀態將被共享。好處是來自兩個實例的可觀察物件可以一起運作,缺點是 MobX 版本必須匹配。**預設值:false
**。
configure({ isolateGlobalState: true })
reactionScheduler: (f: () => void) => void
設定一個執行所有 MobX 反應的新函式。預設情況下,reactionScheduler
只是執行 f
反應,而沒有任何其他行為。這對於基本除錯或減慢反應速度以視覺化應用程式更新很有用。**預設值:f => f()
**。
configure({
reactionScheduler: (f): void => {
console.log("Running an event after a delay:", f)
setTimeout(f, 100)
}
})