補丁代碼?
有時,我們需要自定義UI的工作方式。許多常見需求都可以通過一些支持的API來實現。例如,所有的注冊表都是很好的擴展點:字段注冊表允許添加/刪除專門的字段組件,或者主組件注冊表允許添加應始終顯示的組件。
然而,在某些情況下,這是不夠的。在這些情況下,我們可能需要直接修改一個對象或類。為了實現這一點,Odoo提供了實用函數 patch
。它主要用于覆蓋/更新某些其他組件/代碼片段的行為,這些組件/代碼片段不受我們控制。
描述?
補丁函數位于 @web/core/utils/patch
:
- patch(obj, patchName, patchValue, options)?
- 參數
obj (
Object()
) – 應該被打補丁的對象patchName (
string()
) – 描述補丁的唯一字符串patchValue (
Object()
) – 一個將每個鍵映射到 patchValue 的對象options (
Object()
) – 選項對象(見下文)
patch
函數會直接修改obj
對象(或類),并應用patchValue
對象中描述的所有鍵/值。此操作在patchName
名稱下注冊,因此如果需要,可以稍后取消補丁。大多數補丁操作都可以通過使用
_super
屬性來訪問父級值(請參見下面的示例)。為此,patch
方法會將每個鍵/值對都包裝在一個 getter 中,動態綁定_super
。唯一的選項是
pure (boolean)
。如果設置為true
,則補丁操作不會綁定_super
屬性。
補丁一個簡單對象?
這是一個簡單的示例,展示了如何對一個對象進行打補?。?/p>
import { patch } from "@web/core/utils/patch";
const object = {
field: "a field",
fn() {
// do something
},
};
patch(object, "patch name", {
fn() {
// do things
},
});
當我們打補丁時,通常希望能夠訪問“parent”函數。由于我們使用的是補丁對象,而不是ES6類,因此我們無法使用本地的“super”關鍵字。因此,Odoo提供了一種特殊的方法來模擬這種行為: this._super
:
patch(object, "_super patch", {
fn() {
this._super(...arguments);
// do other things
},
});
警告
每次調用補丁函數后, this._super
都會被重新賦值。這意味著,如果您在補丁中使用異步函數,則不能在 await
后調用 this._super
,因為它可能是您期望的函數,也可能不是。正確的方法是保留對初始 _super
方法的引用:
patch(object, "async _super patch", {
async myAsyncFn() {
const _super = this._super.bind(this);
await Promise.resolve();
await _super(...arguments);
// await this._super(...arguments); // this._super is undefined.
},
});
也支持 getter 和 setter:
patch(object, "getter/setter patch", {
get number() {
return this._super() / 2;
},
set number(value) {
this._super(value * 2);
},
});
修補 JavaScript 類?
patch
函數旨在與任何東西一起使用:對象或 ES6 類。
然而,由于JavaScript類使用原型繼承,當我們希望修補類的標準方法時,實際上需要修補 prototype
:
class MyClass {
static myStaticFn() {...}
myPrototypeFn() {...}
}
// this will patch static properties!!!
patch(MyClass, "static patch", {
myStaticFn() {...},
});
// this is probably the usual case: patching a class method
patch(MyClass.prototype, "prototype patch", {
myPrototypeFn() {...},
});
此外,Javascript 以一種特殊的本地方式處理構造函數,這使得它無法被修補。唯一的解決方法是調用原始構造函數中的一個方法,然后修補該方法:
class MyClass {
constructor() {
this.setup();
}
setup() {
this.number = 1;
}
}
patch(MyClass.prototype, "constructor", {
setup() {
this._super(...arguments);
this.doubleNumber = this.number * 2;
},
});
警告
無法直接修補類的 constructor
!
補丁組件?
組件由JavaScript類定義,因此上述所有信息仍然有效。出于這些原因,Owl組件應該使用 setup
方法,以便它們也可以輕松地進行修補(請參見: 最佳實踐 )。
patch(MyComponent.prototype, "my patch", {
setup() {
useMyHook();
},
});
移除一個補丁?
patch
函數有一個對應的函數 unpatch
,也位于 @web/core/utils/patch
中。
- unpatch(obj, patchName)?
- 參數
obj (
Object()
) – 應該取消打補丁的對象patchName (
string()
) – 描述應該被移除的補丁的字符串
從對象
obj
中移除現有的補丁。這在測試過程中非常有用,當我們在測試開始時對某些內容進行了補丁,然后在測試結束時取消補丁。patch(object, "patch name", { ... }); // test stuff here unpatch(object, "patch name");