• odoo16前端框架分析1 boot.js


    odoo16前端框架分析1 boot.js

    odoo16的前端基于owl组件系统,这是一个类似vue,react的现代js框架。
    前端框架都放在了web模块中,具体的位置是addons/web/static/src
    不过今天要说的不是owl,而是跟前端启动有关的几个重要文件

    1、boot.js

    从名字就能看出来,这个文件是一个启动文件。 odoo前端将所有的js打包成了两个文件,一个是common.js,另一个是backend.js, 而common.js 是最先加载的,而boot.js在common.js中又是最先加载的,可见它的重要性

    odoo自定义了一个小型的模块系统,用于管理各odoo模块中的前端代码,并自行解决各代码之间的依赖关系。相关代码在addons/web/static/src/js/boot.js中,所以这个资源文件是需要第一个加载的文件。

    boot.js在启动时,会创建一个全局的变量’odoo’,该变量有几个预设的函数,用于管理每个javascript模块。每个js模块其实就是一段代码,具有名称或者可能的依赖关系。

     if (!globalThis.odoo) {
            globalThis.odoo = {};
        }
        var odoo = globalThis.odoo;
    
    • 1
    • 2
    • 3
    • 4

    这里定义了一个全局变量odoo,提一下globalThis,这是为了兼容node环境和浏览器环境而创造出的js环境下的顶层对象,在浏览器环境下跟window对象是一样的。

    然后定义了odoo对象的一些属性和函数,我们最常见的就是odoo.define

     odoo.define = function () {
            var args = Array.prototype.slice.call(arguments);
            var name = typeof args[0] === "string" ? args.shift() : "__odoo_job" + jobUID++;
            var factory = args[args.length - 1];
            var deps;
            if (args[0] instanceof Array) {
                deps = args[0];
            } else {
                deps = [];
                factory
                    .toString()
                    .replace(commentRegExp, "")
                    .replace(cjsRequireRegExp, function (match, dep) {
                        deps.push(dep);
                    });
            }
    
            if (!(deps instanceof Array)) {
                throw new Error("Dependencies should be defined by an array", deps);
            }
            if (typeof factory !== "function") {
                throw new Error("Factory should be defined by a function", factory);
            }
            if (typeof name !== "string") {
                throw new Error("Invalid name definition (should be a string", name);
            }
            if (name in factories) {
                throw new Error("Service " + name + " already defined");
            }
    
            factory.deps = deps;
            factories[name] = factory;
    
            let promiseResolve;
            const promise = new Promise((resolve) => {
                promiseResolve = resolve;
            });
            jobs.push({
                name: name,
                factory: factory,
                deps: deps,
                resolve: promiseResolve,
                promise: promise,
            });
    
            deps.forEach(function (dep) {
                jobDeps.push({ from: dep, to: name });
            });
    
            odoo.__DEBUG__.processJobs();
        };
    
    • 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

    这个函数是定义odoo前端模块的函数。它可以有两个或者三个参数

    两个参数,在模块中定义依赖关系。

    odoo.define('module.A', function (require) {
     
        "use strict";
     
        var A = ...;
     
        return A;
     
    });
    
    odoo.define('module.B', function (require) {
     
        "use strict";
     
        var A = require('module.A');
     
        var B = ...; // something that involves A
     
        return B;
     
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    上面的odoo.define()用于标准的odoo定义前端js模块的函数,第一个参数表示这个模块的名称,如果后面没有其它地方继承此js模块,也可以不用取名。第二个参数是一个匿名函数,传入参数为require,这个函数就是实际的js业务代码。如果你想引用其它的js模块,可以通过require(‘module.A’)的语法引入。这里的require名称是固定的,不能改变。另外odoo.define()也提供了一种显式的依赖定义方法,如:

    odoo.define('module.Something', ['module.A', 'module.B'], function (require) {
     
        "use strict";
    
        var A = require('module.A');
     
        var B = require('module.B');
     
        // some code
     
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    从上面的实例中,我们可以看出odoo.define()函数有三个参数:

    • moduleName:javascript模块的名称。它应该是一个唯一的字符串。约定是odoo插件的名称,后跟一个特定的描述。例如"web.Widget"描述了在Web插件中定义的模块,该模块导出Widget类(因为首字母大写),如果名称不是唯一的,则将引发异常并将其显示在控制台中。如果你定义的时候,没有此参数,则系统会自动生成一个带时间戳的唯一名称;
    • dependencies:第二个参数是可选的。如果给出的话,它应该是一个字符串列表,每个字符串对应一个javascript模块名称。这描述了执行模块之前需要加载的依赖项。如果此处未明确给出依赖项,则模块系统将通过在函数上调用toString,然后使用正则表达式查找所有require语句,从函数中提取它们;
    • function:最后一个参数是定义模块的函数。它的返回值是模块的值,可以将其传递给需要它的其他模块。请注意,异步模块有一个小例外,下面会讲到。

    在Odoo中,有可能模块在准备好之前需要执行一些工作。例如,它可以执行rpc加载一些数据。在这种情况下,模块简单地返回一个Promise。 这时,在注册模块之前模块系统将仅等待Promise完成。

    参考 https://www.cnblogs.com/pythonClub/p/17305994.html

  • 相关阅读:
    后端 | 如何卸载 setup.py 安装 python 包 | Python
    函数式接口
    1048 Find Coins
    C语言 typedef
    算法练习5——多数元素
    交换机与路由器技术:远程管理交换机和路由器工作原理、路由器转发数据包的封装过程
    细胞膜修饰金属有机骨架/上转换纳米粒子/仿生温敏水凝胶载体/纳米碳球的制备
    安全防御——二、ENSP防火墙实验学习
    【kali-信息收集】枚举——DNS枚举:DNSenum、fierce
    【Redis】SortedSet类型
  • 原文地址:https://blog.csdn.net/jiafeitutu/article/details/134275090