Kód javítása

Néha szükség van a felhasználói felület működésének testreszabására. Számos általános igényt lefed néhány támogatott API. Például minden regiszter jó kiterjesztési pont: a mező regiszter lehetővé teszi speciális mező komponensek hozzáadását/eltávolítását, vagy a fő komponens regiszter lehetővé teszi olyan komponensek hozzáadását, amelyeknek mindig meg kell jelenniük.

Azonban vannak olyan helyzetek, amikor ez nem elegendő. Ilyen esetekben szükség lehet egy objektum vagy osztály helyben történő módosítására. Ennek eléréséhez az Odoo biztosítja a patch segédfüggvényt. Ez leginkább akkor hasznos, ha valaki más komponensének/kódrészletének viselkedését kell felülírni/frissíteni, amelyet nem irányít.

Leírás

A patch függvény a @web/core/utils/patch helyen található:

patch(objToPatch, extension)
Argumentum
  • objToPatch (object()) – az objektum, amelyet javítani kell

  • extension (object()) – egy objektum, amely minden kulcsot egy kiterjesztéshez rendel

Visszatérési érték

egy függvény a javítás eltávolítására

A patch függvény helyben módosítja az objToPatch objektumot (vagy osztályt), és alkalmazza az extension objektumban leírt összes kulcs/érték párost. Egy unpatch függvényt ad vissza, így szükség esetén később eltávolítható a javítás.

A legtöbb javítási művelet hozzáférést biztosít a szülő értékhez a natív super kulcsszó használatával (lásd alább a példákban).

Egy egyszerű objektum javítása

Itt van egy egyszerű példa arra, hogyan lehet egy objektumot javítani:

import { patch } from "@web/core/utils/patch";

const object = {
  field: "a field",
  fn() {
    // do something
  },
};

patch(object, {
  fn() {
    // do things
  },
});

Amikor függvényeket javítunk, általában szeretnénk hozzáférni a parent függvényhez. Ehhez egyszerűen használhatjuk a natív super kulcsszót:

patch(object, {
  fn() {
    super.fn(...arguments);
    // do other things
  },
});

Figyelem

A super csak metódusban használható, nem függvényben. Ez azt jelenti, hogy a következő konstrukciók érvénytelenek javascript esetén.

const obj = {
  a: function () {
    // Throws: "Uncaught SyntaxError: 'super' keyword unexpected here"
    super.a();
  },
  b: () => {
    // Throws: "Uncaught SyntaxError: 'super' keyword unexpected here"
    super.b();
  },
};

Getterek és setterek is támogatottak:

patch(object, {
  get number() {
    return super.number / 2;
  },
  set number(value) {
    super.number = value;
  },
});

Egy javascript osztály javítása

A patch függvény úgy van tervezve, hogy bármivel működjön: objektummal vagy ES6 osztállyal.

Azonban, mivel a javascript osztályok prototípusos örökléssel működnek, amikor valaki egy osztály standard metódusát kívánja javítani, akkor valójában a prototype-ot kell javítanunk:

class MyClass {
  static myStaticFn() {...}
  myPrototypeFn() {...}
}

// this will patch static properties!!!
patch(MyClass, {
  myStaticFn() {...},
});

// this is probably the usual case: patching a class method
patch(MyClass.prototype, {
  myPrototypeFn() {...},
});

Továbbá, a Javascript a konstruktort egy speciális natív módon kezeli, ami lehetetlenné teszi annak javítását. Az egyetlen megoldás, hogy az eredeti konstruktorban egy metódust hívunk meg, és azt a metódust javítjuk:

class MyClass {
  constructor() {
    this.setup();
  }
  setup() {
    this.number = 1;
  }
}

patch(MyClass.prototype, {
  setup() {
    super.setup(...arguments);
    this.doubleNumber = this.number * 2;
  },
});

Figyelem

Lehetetlen közvetlenül egy osztály constructor-át javítani!

Egy komponens javítása

A komponenseket javascript osztályok határozzák meg, így a fenti információk továbbra is érvényesek. Ezek miatt az Owl komponenseknek a setup metódust kell használniuk, így könnyen javíthatók is (lásd a best practices szakaszt).

patch(MyComponent.prototype, {
  setup() {
    useMyHook();
  },
});

Egy javítás eltávolítása

A patch függvény visszaadja az ellentétét. Ez főként tesztelési célokra hasznos, amikor egy teszt elején javítunk valamit, és a végén visszaállítjuk.

const unpatch = patch(object, { ... });
// test stuff here
unpatch();

Ugyanazon javítás alkalmazása több objektumra

Előfordulhat, hogy valaki ugyanazt a javítást szeretné több objektumra alkalmazni, de a super kulcsszó működése miatt az extension csak egyszer használható javításra, és nem másolható/klónozható (nézze meg a kulcsszó dokumentációját). Egy függvény, amely visszaadja a javításhoz használt objektumot, egyedivé teheti azt.

const obj1 = {
  method() {
    doSomething();
  },
};

const obj2 = {
  method() {
    doThings();
  },
};

function createExtensionObj() {
  return {
    method() {
      super.method();
      doCommonThings();
    },
  };
}

patch(obj1, createExtensionObj());
patch(obj2, createExtensionObj());

Figyelem

Ha egy extension egy másikra épül, akkor a két kiterjesztést külön kell alkalmazni. Ne másolja/klónozza a kiterjesztést.

const object = {
  method1() {
    doSomething();
  },
  method2() {
    doAnotherThing();
  },
};

const ext1 = {
  method1() {
    super.method1();
    doThings();
  },
};

const invalid_ext2 = {
  ...ext1, // this will not work: super will not refer to the correct object in methods coming from ext1
  method2() {
    super.method2();
    doOtherThings();
  },
};

patch(object, invalid_ext2);
object.method1(); // throws: Uncaught TypeError: (intermediate value).method1 is not a function

const valid_ext2 = {
  method2() {
    super.method2();
    doOtherThings();
  },
};

patch(object, ext1); // first patch base extension
patch(object, valid_ext2); // then the new one
object.method1(); // works as expected