Odoo10 - Building Interface Extensions - 1

這一篇教程主要是爲了創建 web client 的 module。

A Simple Module

讓我們從一個基本的包含web組件配置的odoo module開始,並測試web framework。
例子可以從下面的命令下載

$ git clone https://github.com/odoo/petstore

執行上面的命令後,將在當前文件目錄下創建一個petstore文件夾,將這個目錄加入到 odoo 的 addons-path中,然後創建一個新的db,並且安裝這個模塊。
文件的目錄如下

oepetstore/
├── images
│   ├── alligator.jpg
│   ├── ball.jpg
│   ├── crazy_circle.jpg
│   ├── fish.jpg
│   └── mice.jpg
├── __init__.py
├── oepetstore.message_of_the_day.csv
├── __openerp__.py
├── petstore_data.xml
├── petstore.py
├── petstore.xml
└── static
    └── src
        ├── css
        │   └── petstore.css
        ├── js
        │   └── petstore.js
        └── xml
            └── petstore.xml

6 directories, 14 files

此模塊已經定義了各種的服務配置。我們稍後再細說,先將目光集中在與web相關的內容上,也就是static這個文件夾的內容。
所有web要用到的文件必須放在static文件夾下面,這樣才能被瀏覽器等所訪問到,此文件夾之外的文件則不能被瀏覽器直接訪問。src/css, src/js, src/xml子文件夾不是必須的,只是通常的文件放置習慣。
oepetstore/static/css/petstore.css, 目前爲空,用來存放pet store的css
oepetstore/static/xml/petstore.xml,通常爲空,放置Qweb模板
oepetstore/static/js/petstore.js,最重要的就是這個文件了,包含了此模塊的各種業務邏輯,通常應該長成這樣:

odoo.oepetstore = function(instance, local) {
    var _t = instance.web._t,
        _lt = instance.web._lt;
    var QWeb = instance.web.qweb;

    local.HomePage = instance.Widget.extend({
        start: function() {
            console.log("pet store home page loaded");
        },
    });

    instance.web.client_actions.add(
        'petstore.homepage', 'instance.oepetstore.HomePage');
}

僅僅用來在瀏覽器的console上,輸出一小段message。
static目錄下的所有文件都必須在模塊文件裏面定義好,這樣才能被自動的正確的導入。src/xml下的所有東西,都在__manifest__.py文件中設置了導入,其他的css, js則是定義在petstore.xml中。

提示
所有的js文件都會被自動的壓縮,最小化。這導致前端調試起來非常的困難,但是,你可以通過開啓odoo的調試模式來避免這個

Odoo JavaScript Module

JavaScript沒有模塊這一概念,導致在各個文件中的javascript代碼可能會互相沖突。Odoo爲了解決這一問題,提供了自己定義方式,用來避免各種衝突。
oepetstore/static/js/petstore.js 包含了一個module定義

odoo.oepetstore = function(instance, local) {
    local.xxx = ...;
}

在 Odoo web中,module的是像定義function一樣被綁在odoo變量上。function的name必須和addon的名字一樣(也就是oepetstore),這樣 web framework才能找到它,並且自動的實例化它。
當web client導入你的module時,它會自動調用此方法,並且傳入兩個參數。

  • 第一個是當前 web client 的實例,通過它可以調用到odoo定義好的各種東西(如:翻譯,network service)等,還有其他module或者 core定義的各種objects.
  • 第二個是自己模塊的命名空間,對其添加各種屬性,使得這個module的一些東西可以被外部訪問。

Classes

如同 module一樣,javascript沒有像其他面向對象的語言一樣提供內置的Class,雖然提供了一個粗糙的基於原型鏈的東西。
爲了方便開發,Odoo提供了一個Class,實現基本的繼承等。
創建一個新的Class,需要調用odoo.web.Class()extend()方法:

var MyClass = instance.web.Class.extend({
    say_hello: function(){
        console.log("hello");
    }
});

extend()方法接受一個字典,包含一些方法以及屬性。在上面的例子中,只有一個不接受參數的say_hello方法。
通過new關鍵字實例化一個類

var my_object = new MyClass();
my_object.say_hello();
// print "hello" in the console

通過 this來訪問屬性


var MyClass = instance.web.Class.extend({
    say_hello: function() {
        console.log("hello", this.name);
    },
});

var my_object = new MyClass();
my_object.name = "Bob";
my_object.say_hello();
// print "hello Bob" in the console

類也提供了一個類似的構造函數,用來執行一些初始化。需要定義init()方法,參數由 new 的時候傳入。

var MyClass = instance.web.Class.extend({
    init: function(name) {
        this.name = name;
    },
    say_hello: function() {
        console.log("hello", this.name);
    },
});

var my_object = new MyClass("Bob");
my_object.say_hello();
// print "hello Bob" in the console

也可以從已經定義好的Class中再extend一個Class作爲其子類

var MySpanishClass = MyClass.extend({
    say_hello: function() {
        console.log("hola", this.name);
    },
});

var my_object = new MySpanishClass("Bob");
my_object.say_hello();
// print "hola Bob" in the console

當覆寫父類的方法時,可以通過this._super()調用父類的方法。

var MySpanishClass = MyClass.extend({
    say_hello: function() {
        this._super();
        console.log("translation in Spanish: hola", this.name);
    },
});

var my_object = new MySpanishClass("Bob");
my_object.say_hello();
// print "hello Bob \n translation in Spanish: hola Bob" in the console

警告
_super並不是一個標準方法,它是調用當前繼承連上的下一個元素的方法,並且只能是在同步的方法中調用。異步的方式是不能直接使用的(包括網絡調用,或者setTimeout回調)。

// broken, will generate an error
say_hello: function () {
    setTimeout(function () {
        this._super();
    }.bind(this), 0);
}

// correct
say_hello: function () {
    // don't forget .bind()
    var _super = this._super.bind(this);
    setTimeout(function () {
        _super();
    }.bind(this), 0);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章