odoo.define

发布时间 2023-04-11 14:01:27作者: CrossPython

前面我们讲到了odoo的前端js加载以及怎么把自己写的js插入odoo的框架中。那在这里,有些人就会问了,odoo的模块安装是乱序的,我们怎么保证前端js在执行的时候,那些依赖的底层包已经加载了呢?如果两个模块之间有依赖关系,那在上一节讲的前端继承加载的位置是否有要注意的呢?

其实这些都不用担心,odoo已经为我们考虑好这些情况了,它自定义了一个小型的模块系统,用于管理各odoo模块中的前端代码,并自行解决各代码之间的依赖关系。相关代码在addons/web/static/src/js/boot.js中,所以这个资源文件是需要第一个加载的文件。

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

举个例子,我们看如下脚本:

 

// in file a.js

odoo.define('module.A', function (require) {

    "use strict";

    var A = ...;

    return A;

});



// in file b.js

odoo.define('module.B', function (require) {

    "use strict";

    var A = require('module.A');

    var B = ...; // something that involves A

    return B;

});

  

 

上面的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

});

  

 

define的第二个参数是列表类型时,odoo认为这里是定义的模块依赖。

如果在你的模块中,需要引用到其它的模块,而你又没有定义依赖关系,或者依赖模块名称写错了,则依赖的模块不会被加载,并且在浏览器的控制台将提供错误日志。另外在定义时,需要注意不要有嵌套的循环依赖,这将造成系统的错误。

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

  • moduleName:javascript模块的名称。它应该是一个唯一的字符串。约定是odoo插件的名称,后跟一个特定的描述。例如"web.Widget"描述了在Web插件中定义的模块,该模块导出Widget类(因为首字母大写),如果名称不是唯一的,则将引发异常并将其显示在控制台中。如果你定义的时候,没有此参数,则系统会自动生成一个带时间戳的唯一名称;

  • dependencies:第二个参数是可选的。如果给出的话,它应该是一个字符串列表,每个字符串对应一个javascript模块名称。这描述了执行模块之前需要加载的依赖项。如果此处未明确给出依赖项,则模块系统将通过在函数上调用toString,然后使用正则表达式查找所有require语句,从函数中提取它们;

  • function:最后一个参数是定义模块的函数。它的返回值是模块的值,可以将其传递给需要它的其他模块。请注意,异步模块有一个小例外,下面会讲到。

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

 

odoo.define('module.Something', function (require) {

    "use strict";

    var ajax = require('web.ajax');

    return ajax.rpc(...).then(function (result) {

        // some code here

        return something;

    });

});