当前位置: 首页 > news >正文

odoo前端js对象的扩展方法

odoo前端js对象的扩展方法

在 Odoo 中,你可以使用两种方法来扩展 JavaScript 对象:extendspatch。这两种方法在功能上有一些区别。

  1. extends 方法:

    • 使用 extends 方法可以创建一个新的 JavaScript 对象,并继承自现有的对象。这意味着你可以在新对象中添加、修改或覆盖现有对象的属性和方法。
    • extends 方法适用于对现有对象进行全面的扩展和修改,以满足特定的需求。你可以通过创建一个新的对象,并在其中添加自定义的属性和方法来实现扩展。
    • 使用 extends 方法时,你需要确保新对象的原型链正确设置,以便正确继承和覆盖现有对象的属性和方法。
  2. patch 方法:

    • 使用 patch 方法可以直接修改现有的 JavaScript 对象,而无需创建新的对象。你可以通过 patch 方法来修改对象的属性和方法,添加新的属性和方法,或者删除现有的属性和方法。
    • patch 方法适用于对现有对象进行局部的修改和调整,以满足特定的需求。你可以直接在现有对象上进行修改,而无需创建新的对象。
    • 使用 patch 方法时,你需要确保正确地定位到要修改的对象,并进行相应的修改操作。

总的来说,extends 方法适用于全面的扩展和修改,而 patch 方法适用于局部的修改和调整。选择使用哪种方法取决于你的具体需求和场景。

1、patch的实现

patch 一个简单的例子

/** @odoo-module **/import { _t } from "@web/core/l10n/translation";
import { patch } from "@web/core/utils/patch";
import { SearchBar } from "@web/search/search_bar/search_bar";patch(SearchBar.prototype, {getPreposition(searchItem) {let preposition = super.getPreposition(searchItem);if (this.fields[searchItem.fieldName].name == 'payment_date') {preposition = _t("until");}return preposition}
});

2、patch.js

先学习一下object对象,再来学习patch.js

patch对象的原型,调用了很多Object的静态方法,原则上就是在原型对象上动态增加或者替换新的属性。

        // Replace the old property by the new one.Object.defineProperty(objToPatch, key, newProperty);

附录: patch.js 源文件

/** @odoo-module **//***  @typedef {{*      originalProperties: Map<string, PropertyDescriptor>;*      skeleton: object;*      extensions: Set<object>;*  }} PatchDescription*//** @type {WeakMap<object, PatchDescription>} */
const patchDescriptions = new WeakMap();/*** Create or get the patch description for the given `objToPatch`.* @param {object} objToPatch* @returns {PatchDescription}*/
function getPatchDescription(objToPatch) {if (!patchDescriptions.has(objToPatch)) {patchDescriptions.set(objToPatch, {originalProperties: new Map(),skeleton: Object.create(Object.getPrototypeOf(objToPatch)),extensions: new Set(),});}return patchDescriptions.get(objToPatch);
}/*** @param {object} objToPatch* @returns {boolean}*/
function isClassPrototype(objToPatch) {// class A {}// isClassPrototype(A) === false// isClassPrototype(A.prototype) === true// isClassPrototype(new A()) === false// isClassPrototype({}) === falsereturn Object.hasOwn(objToPatch, "constructor") && objToPatch.constructor?.prototype === objToPatch;
}/*** Traverse the prototype chain to find a potential property.* @param {object} objToPatch* @param {string} key* @returns {object}*/
function findAncestorPropertyDescriptor(objToPatch, key) {let descriptor = null;let prototype = objToPatch;do {descriptor = Object.getOwnPropertyDescriptor(prototype, key);prototype = Object.getPrototypeOf(prototype);} while (!descriptor && prototype);return descriptor;
}/*** Patch an object** If the intent is to patch a class, don't forget to patch the prototype, unless* you want to patch static properties/methods.** @template T* @template {T} U* @param {T} objToPatch The object to patch* @param {U} extension The object containing the patched properties* @returns {() => void} Returns an unpatch function*/
export function patch(objToPatch, extension) {if (typeof extension === "string") {throw new Error(`Patch "${extension}": Second argument is not the patch name anymore, it should be the object containing the patched properties`);}const description = getPatchDescription(objToPatch);description.extensions.add(extension);const properties = Object.getOwnPropertyDescriptors(extension);for (const [key, newProperty] of Object.entries(properties)) {const oldProperty = Object.getOwnPropertyDescriptor(objToPatch, key);if (oldProperty) {// Store the old property on the skeleton.Object.defineProperty(description.skeleton, key, oldProperty);}if (!description.originalProperties.has(key)) {// Keep a trace of original property (prop before first patch), useful for unpatching.description.originalProperties.set(key, oldProperty);}if (isClassPrototype(objToPatch)) {// A property is enumerable on POJO ({ prop: 1 }) but not on classes (class A {}).// Here, we only check if we patch a class prototype.newProperty.enumerable = false;}if ((newProperty.get && 1) ^ (newProperty.set && 1)) {// get and set are defined together. If they are both defined// in the previous descriptor but only one in the new descriptor// then the other will be undefined so we need to apply the// previous descriptor in the new one.const ancestorProperty = findAncestorPropertyDescriptor(objToPatch, key);newProperty.get = newProperty.get ?? ancestorProperty?.get;newProperty.set = newProperty.set ?? ancestorProperty?.set;}// Replace the old property by the new one.Object.defineProperty(objToPatch, key, newProperty);}// Sets the current skeleton as the extension's prototype to make// `super` keyword working and then set extension as the new skeleton.description.skeleton = Object.setPrototypeOf(extension, description.skeleton);return () => {// Remove the description to start with a fresh base.patchDescriptions.delete(objToPatch);for (const [key, property] of description.originalProperties) {if (property) {// Restore the original property on the `objToPatch` object.Object.defineProperty(objToPatch, key, property);} else {// Or remove the property if it did not exist at first.delete objToPatch[key];}}// Re-apply the patches without the current one.description.extensions.delete(extension);for (const extension of description.extensions) {patch(objToPatch, extension);}};
}
http://www.lryc.cn/news/230562.html

相关文章:

  • 力扣双周赛 -- 117(容斥原理专场)
  • 基于Rabbitmq和Redis的延迟消息实现
  • Masked Relation Learning for DeepFake Detection
  • R语言爬虫程序自动爬取图片并下载
  • 2023年10月国产数据库大事记-墨天轮
  • Linux内核分析(十四)--内存管理之malloc、free 实现原理
  • Hive函数
  • 教资笔记(目录)
  • np.repeat()的注意事项
  • 239. 滑动窗口最大值
  • c++ barrier 使用详解
  • c# 接口
  • 1、NPC 三电平SVPWM simulink仿真
  • JAVA对象列表强转失败,更好的方法
  • 2023最新版本 从零基础入门C++与QT(学习笔记) -5- 动态内存分配(new)
  • asp.net校园招聘管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio
  • flink的键值分区状态自动过期ttl配置
  • 解决Mac配置maven环境后,关闭终端后环境失效的问题(适用于所有终端关闭后环境失效的问题)
  • springboot运行jar包,实现复制jar包resources下文件、文件夹(可支持包含子文件夹)到指定的目录
  • Webpack Bundle Analyzer包分析器
  • SQL-----STUDENT
  • OpenCV入门——图像视频的加载与展示一些API
  • Control的Invoke和BeginInvoke
  • 什么是OpenCL?
  • AdaBoost:提升机器学习的力量
  • Pikachu(皮卡丘靶场)初识XSS(常见标签事件及payload总结)
  • 一则DNS被重定向导致无法获取MySQL连接处理
  • Vue3中如何使用this
  • 7.jvm对象内存布局
  • U-boot(一):Uboot命令和tftp