This page looks best with JavaScript enabled

Odoo JavaScript - Phần 2: Tổng quan về classes và kiến trúc MVC trong Odoo

 ·  ☕ 3 phút đọc · 👀... views

Bài viết lần này, chúng ta cùng đi tìm hiểu sâu hơn về web.Widget class nhé!

Bên cạnh việc extend từ những mixin khác như ở phần 1 mình có nói thì mục đích chính của web.Widget đó chính là render Qweb, thực hiện quản lý life cycle và thêm vào DOM.

Web.Widget có các thuộc tính lấy cảm hứng từ BackboneJS hiển thị trong lớp như tagName,id, className, attributes, events, template

xmlDependencies, cssLibs, jsLibs và assetLibs là những thức sẽ được tìm và load trước khi Widget được render.

Cần chú ý, ***web.Widget có 2 thuộc tính ẩn rất quan trọng như sau:

  • el: là 1 DOM element được set giá trị khi chúng ta gọi hàm setElement
  • $el : là biến Jquery đại diện cho el
    Chú ý: Nếu bạn muốn truy cập đến this.el hoặc this.$el ở sai thời điểm của life cycle thì có thể trả về là undifine, 2 thuộc tính này chỉ có giá trị khi chúng ta hàm renderElement hoặc hàm attach to được gọi.

Render template Qweb

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
/**
     * Renders the element. The default implementation renders the widget using
     * QWeb, `this.template` must be defined. The context given to QWeb contains
     * the "widget" key that references `this`.
     */
    renderElement: function () {
        var $el;
        if (this.template) {
            $el = $(core.qweb.render(this.template, {widget: this}).trim());
        } else {
            $el = this._makeDescriptive();
        }
        this._replaceElement($el);
    },

Lifecycle

Vòng đời của 1 widget bao gồm init -> willStart ->[rendering]-> start -> destroy, tương ứng với các hàm có trong Widget.

  • Hàm init
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
init: function (parent) {
        mixins.PropertiesMixin.init.call(this);
        this.setParent(parent);
        // Bind on_/do_* methods to this
        // We might remove this automatic binding in the future
        for (var name in this) {
            if(typeof(this[name]) === "function") {
                if((/^on_|^do_/).test(name)) {
                    this[name] = this[name].bind(this);
                }
            }
        }
    },
  • Hàm willStart sẽ thực hiện bất đồng bộ việc tải thư viện liên quan, file xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
* @returns {Promise}
     */
    willStart: function () {
        var proms = [];
        if (this.xmlDependencies) {
            proms.push.apply(proms, _.map(this.xmlDependencies, function (xmlPath) {
                return ajax.loadXML(xmlPath, core.qweb);
            }));
        }
        if (this.jsLibs || this.cssLibs || this.assetLibs) {
            proms.push(this._loadLibs(this));
        }
        return Promise.all(proms);
    },
  • Hàm start
1
2
3
4
5
 * @returns {Promise}
     */
    start: function () {
        return Promise.resolve();
    },
  • Hàm destroy sẽ loại bỏ $ el khỏi DOM và xóa các phần tử con.
1
2
3
4
5
6
destroy: function () {
        mixins.PropertiesMixin.destroy.call(this);
        if (this.$el) {
            this.$el.remove();
        }
    },

Insert DOM

web.Widget có các hàm appendTo, insertAfter, attachTo, prependTo đều nhận đối số là 1 jquery element, bạn có thể tìm hiểu thêm trong code core của Odoo.

Tổng kết

Widget là 1 trong những thành phần quan trọng nhất của Framework, mình khuyên bạn nên dành thời gian đi sâu vào mã nguồn, đọc lại phần giải thích của mình và xem qua tài liệu này

Chia sẻ
Support the author with

Hùng Phạm
Viết bởi
Hùng Phạm
Web/Mobile Developer