1.web模块
注意,
odoo模块中web部分用到的所有文件必须被放置在模块内的static文件夹里。这是强制性的,出于安全考虑。
事实上,我们创建的文件夹CSS,JS和XML,仅仅是一个习惯。
static文件夹
oepetstore/static/css/petstore.css是我们的CSS文件。
oepetstore/static/xml/petstore.xml是一个XML文件,将包含我们QWeb的模板。
oepetstore/static/js/petstore.js包含应用程序的JavaScript代码。
像odoo的XML文件包含了视图或数据一样,必须在__
odoo__.py文件内标明这些文件。下面是我们增加的行,它告诉web client必须记载这些文件:
'js':['static/src/js/*.js'],
'css':['static/src/css/*.css'],
'qweb':['static/src/xml/*.xml'],
odoo内,默认会把所有的JavaScript文件连接为一个文件。然后,我们执行一个叫minification的操作。
minification将移除文件中的所有的注释、空格和换行符。最后,发送这个文件给用户浏览器。
但这么做的缺点,是无法调试应用程序。为了避免这种副作用,仍然能够调试的解决办法是:在
odoo的URL后面添加一个参数?debug.
添加后的URL:http://localhost:8069/?debug
当您使用带debug参数的URL,应用程序将不会执行串联所有minification的JavaScript文件这个过程。应用程序也将需要更多的时间来加载,但你能进
行调试开发了。
在前面的章节中,我们解释了JavaScript缺少命名空间机制,来分割在不同的JavaScript文件中声明的变量。并且我们提出了模块模式这个简单方法。
模块模式(如app.js文件):
(function(){
app={};
function main(){
console.log("launch application");
};
app.main=main;
})();
在
odoo的web框架内,有个类似于模块模式的等价物,集成了该框架的其余部分。请注意,
odoo的Web模块与其他
odoo的addon模块概念上是不同的,一个addon模块是一个包含很多文件的文件夹,web模块仅仅是一个有命名空间概念的JavaScript。
1)模块
oepetstore/static/js/petstore.js声明了这样的模块:
odoo.oepetstore=function(instance){
instance.oepetstore={};
instance.oepetstore.XXX=......;
}
在odoo的Web框架内,通过声明一个函数来声明一个JavaScript模块,并把这个函数放在全局变量.
odoo的属性内.这个属性名称必须和
odoo addon模块名称一致(这addon模块名为oepetstore,我应把函数赋值给odoo.oepetstore属性。如果换成odoo.petstore属性,则无法正常运行)。当Web客户端转载这个addon模块时,该函数将被调用。将传入一个名为instance的参数,这个参数代表当前odoo的Web客户端实例,包含了所有相关当前会话数据,以及所有Web模块的变量。
在instance对象内创建与addon模块名称一致的新命名空间是个惯例。这就是为什么我们在instance.oepetstore设置一个空dictionary。这个dictionary就是命名空间,用来声明我们模块内自己使用的所有类和变量。
2)类
JavaScript不像其他面向对象编程语言那样有类机制。更确切地说,它提供了面向对象编程语言元素,但你必须自己定义,自己选择如何做。
odoo Web框架提供工具来简化这个过程,让程序员以类似其他编程语言,如Java的方式编码。
定义一个新类,你需要从instance.web.Class类继承。语法如下:
instance.oepetstore.MyClass=instance.web.Class.extend({
say_hello:function(){
console.log("hello");
},
});
类的实例化:
var my_object=new instance.oepetstore.MyClass();
my_object.say_hello();
类可以有一个构造函数,它方法名为init()。你可以像大多数开发语言那样,传递参数给构造器:
instance.oepetstore.MyClass=instance.web.Class.extend({ init:function(name){ this.name=name; }, say_hello:function(){ console.log("hello",this.name); }, }); 类的继承 类可以被继承 instance.oepetstore.MySpanishClass=instance.oepetstore.MyClass.extend({ say_hello:function(){ this._super(); console.log("hola",this.name); }, }); var my_object=new instance.oepetstore.MySpanishClass("Nicolas"); my_object.say_hello(); this._super()不是常用的类方法 3)Widgets Basics(基础部件) odoo中Widget部件,是一个通用组件,专门用来向用户显示内容。 oepetstore实例中的petstore.js内容: odoo.oepetstore=function(instance){ var_t=instance.web._t, _lt=instance.web._lt; var QWeb=instance.web.qweb; instance.oepetstore={}; instance.oepetstore.HomePage=instance.web.Widget.extend({ start:function(){ console.log("pet store home page loaded"); }, });
instance.web.client_actions.add('petstore.homepage','instance.oepetstore.HomePage'); } 最后一行代码,把这个部件注册为客户端的action。当我们点击‣Pet Store‣Pet Store‣Home Page菜单项时,客户端action让部件显示出来。 HomePage部件有一个start()方法。在部件初始化后,这方法被自动调用。它已接接受指令去显示其内容。我们将用它向用户显示一些内容。要做到这一点,我们使用所有部件都有的$el属性。该属性是一个jQuery对象,表示部件对应的HTML标签的根标签。部件包含了多个HTML标签,这些HTM标签有一个统一的根标签。默认情况下,部件都有一个空的根标签. 一个HTML标签在没有具体内容的时候,是不可见的。这也解释了为什么显示instance.oepetstore.HomePage时,是个空白区域,它根本没有任何内容。要想显示些内容,我们用jQuery该对象上的一些简单方法,在根标签中添加一些HTML标签: instance.oepetstore.HomePage=instance.web.Widget.extend({ start:function(){ this.$el.append(" Hello dear odoo user!
");},}); 常用方法: appendTo()方法 var pettoys=new instance.oepetstore.PetToysList(this);//实例化PetToysList()部件 pettoys.appendTo(this.$(".oe_petstore_homepage_left"));//把pettoys添加到当前部件的class=.oe_petstore_homepage_left的标签中 注意:new instance.oepetstore.PetToysList(this),其中参数this,代表调用此部件的实例,表示部件的隶属关系。 addClass()方法 this.$el.addClass("oe_petstore_homepage");//添加样式 getParent()方法 用于获取父部件 getChildren()方法 用来获取子部件列表:this.getChildren()[0].$el 当你在部件中重载init()时,必须以父部件作为第一参数传入,并调用传入给this._super(),例如: instance.oepetstore.GreetingsWidget=instance.web.Widget.extend({ init:function(parent,name){ this._super(parent); this.name=name; }, }); 最后,如果一个部件没有父部件(即:在你的应用实例化时是第一个部件),传入null参数: new instance.oepetstore.GreetingsWidget(null); 销毁部件: destroy()方法: 当一个部件被销毁,它会先调用所有子部件的destroy()。然后,它在DOM中清楚自己。通过部件隶属关系的递归调用,避免了内存泄漏,这对容易产生内 存泄露的大型JavaScript应用程序来说是非常有用的。
|