• 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
        }
    });
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2、patch.js

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

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

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

    附录: patch.js 源文件

    /** @odoo-module **/
    
    /**
     *  @typedef {{
     *      originalProperties: Map;
     *      skeleton: object;
     *      extensions: Set;
     *  }} PatchDescription
     */
    
    /** @type {WeakMap} */
    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({}) === false
        return 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);
            }
        };
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
  • 相关阅读:
    Quick MTF 照相机镜头图像质量测试程序-UPDATE
    元组高级用法
    『C++ - 模板』之模板进阶
    ActiveMQ消息中间件简介
    python中使用tflite推理网络
    .NET StackExchange.Redis 操作redis
    PLC梯形图实操——风扇正反转
    预编译(1)
    Qt入门(零)——Qt概述
    Centos7配置NAT网络
  • 原文地址:https://blog.csdn.net/jiafeitutu/article/details/134414588