odoo8 官方web客户端开发文档翻译3---Widgets Basics(基础窗口组件)

Widgets Basics(组件基础)

The Odoo web client bundles jQuery for easy DOM manipulation. It is useful and provides a better API than standard W3C DOM2, but insufficient to structure complex applications leading to difficult maintenance.

odoo web客户端内置了jquery库让你可以进行简单的DOM操作,这是十分有意义的,并且具有比W3C DOM2标准更好的API。但对于复杂应用的使用与维护这还远远不够。

Much like object-oriented desktop UI toolkits (e.g. QtCocoa or GTK), Odoo Web makes specific components responsible for sections of a page. In Odoo web, the base for such components is the Widget() class, a component specialized in handling a page section and displaying information for the user.

如大部分面向对象的桌面级UI工具库(QT,Cocoa GTK等),Odoo web提供了一些用于页面的特定组件。在odoo web,这些组件中有一个基础的组件叫Widget()类。一个专门处理一个页面部分和显示用户信息的组件。

Your First Widget(你的第一个组件)

The initial demonstration module already provides a basic widget:

示例模块的初始化代码以及提供了一个基础的组件

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

It extends Widget() and overrides the standard method start(), which — much like the previous MyClass — does little for now.

它继承扩展了Widget()类并重写了start方法。这有点象前面的MyClass例子,但做得更简单

This line at the end of the file:

示例的js文件最后一行为:

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

registers our basic widget as a client action. Client actions will be explained later, for now this is just what allows our widget to be called and displayed when we select the Pet Store ‣ Pet Store ‣ Home Page menu.

把我们的基础组件注册为一个client action,什么是client action 后面会细讲。现在你只要知道的是,当你选择 Pet Store ‣ Pet Store ‣ Home Page菜单是,这个组件会被调用并显示

Warning(注意)

because the widget will be called from outside our module, the web client needs its "fully qualified" name, not the local version.

因为组件会被外部的模块调用,所以web 客户端需要完全可行的命名(应该是全局唯一),不要只考虑在你的代码范围内


Display Content(显示你的内容)

Widgets have a number of methods and features, but the basics are simple:

组件有很多方法和特性,但基础的应用也很简单:

  • set up a widget           设置一个组件
  • format the widget's data  格式化组件的数据
  • display the widget 显示组件

The HomePage widget already has a start() method. That method is part of the normal widget lifecycle and automatically called once the widget is inserted in the page. We can use it to display some content.

All widgets have a $el which represents the section of page they're in charge of (as a jQuery object). Widget content should be inserted there. By default, $el is an empty <div> element.

<div> element is usually invisible to the user if it has no content (or without specific styles giving it a size) which is why nothing is displayed on the page when HomePage is launched.

Let's add some content to the widget's root element, using jQuery:

HomePage组件已经有一个start()方法了。这个方法作为正常组件生命周期的一部分,一旦组件被页面加载,该方法就会马上被调用,我们可以用这个方法来显示我们的内容。

所有组件都有$el对象代表了他所负责的页面对象(同时他是一个jquery对象)。 组件内容应插入那里。默认情况下,$el是一个空<div>元素。

一个 <div>元素 如果没有内容(或者是样式中没有给他一个大小),通常是用户不可见的,,这就是为什么 首页启动时,没有任何东西显示在页面上。
使用jQuery,我们添加一些内容到部件的根元素:

local.HomePage = instance.Widget.extend({
    start: function() {
        this.$el.append("<div>Hello dear Odoo user!</div>");
    },
});

That message will now appear when you open Pet Store ‣ Pet Store ‣ Home Page

打开Pet Store ‣ Pet Store ‣ Home Page 你会看到信息




Note(小要点)

to refresh the javascript code loaded in Odoo Web, you will need to reload the page. There is no need to restart the Odoo server.

为了更新js代码,你只需要刷新页面就行,不需要重启odoo服务器。

The HomePage widget is used by Odoo Web and managed automatically. To learn how to use a widget "from scratch" let's create a new one:

这个HomePage组件被Odoo web使用并自动管理,为了从零开始学习使用组件,我们创建一个新的

local.GreetingsWidget = instance.Widget.extend({
    start: function() {
        this.$el.append("<div>We are so happy to see you again in this menu!</div>");
    },
});

We can now add our GreetingsWidget to the HomePage by using the GreetingsWidget's appendTo() method:

local.HomePage = instance.Widget.extend({
    start: function() {
        this.$el.append("<div>Hello dear Odoo user!</div>");
        var greeting = new local.GreetingsWidget(this);
        return greeting.appendTo(this.$el);
    },
});
  • HomePage first adds its own content to its DOM root HomePage 先将自己的内容加到DOM根下
  • HomePage then instantiates GreetingsWidget   homePage实例化GreetingsWidget
  • Finally it tells GreetingsWidget where to insert itself, delegating part of its $el to the GreetingsWidget.
  • 最后告诉那个插入自身的GreetingsWidget

When the appendTo() method is called, it asks the widget to insert itself at the specified position and to display its content. Thestart() method will be called during the call to appendTo().

To see what happens under the displayed interface, we will use the browser's DOM Explorer. But first let's alter our widgets slightly so we can more easily find where they are, by adding a class to their root elements:

local.HomePage = instance.Widget.extend({
    className: 'oe_petstore_homepage',
    ...
});
local.GreetingsWidget = instance.Widget.extend({
    className: 'oe_petstore_greetings',
    ...
});

If you can find the relevant section of the DOM (right-click on the text then Inspect Element), it should look like this:

<div class="oe_petstore_homepage">
    <div>Hello dear Odoo user!</div>
    <div class="oe_petstore_greetings">
        <div>We are so happy to see you again in this menu!</div>
    </div>
</div>

Which clearly shows the two <div> elements automatically created by Widget(), because we added some classes on them.

通过添加class标志,我们可以很清楚地看到组件自动创建的div

We can also see the two message-holding divs we added ourselves

Finally, note the e <div class="oe_petstore_greetings">lement which represents the GreetingsWidget instance is inside the<div class="oe_petstore_homepage"> which represents the HomePage instance, since we appended

最后我们注意到代表GreetingsWidget的<div class="oe_petstore_greetings"> 元素是在代表HomePage的div元素里面的

Widget Parents and Children(父子组件)

In the previous part, we instantiated a widget using this syntax:

在前面我们实例化组件用了以下的语法

new local.GreetingsWidget(this);

The first argument is this, which in that case was a HomePage instance. This tells the widget being created which other widget is its parent.

这里的唯一参数this,指的就是HomePage实例,这里告诉系统新的组件将以其作为父组件进行创建

As we've seen, widgets are usually inserted in the DOM by another widget and inside that other widget's root element. This means most widgets are "part" of another widget, and exist on behalf of it. We call the container the parent, and the contained widget thechild.

正如我们所见,组件总是作为DOM被插入到其他组件,而他们总是全部包含在唯一的root元素下。这意味着组件总可以说是其他组件的一部分。我们将包含当前组件的组件叫父组件,而自身包含的组件叫子组件

Due to multiple technical and conceptual reasons, it is necessary for a widget to know who is its parent and who are its children.

由于技术和概念上清晰的原因,我们很有必要知道对于一个组件谁是他的父亲,谁是他的儿子。

getParent()
can be used to get the parent of a widget:: 这个方法可以得到组件的父亲

local.GreetingsWidget = instance.Widget.extend({
    start: function() {
        console.log(this.getParent().$el );
        // will print "div.oe_petstore_homepage" in the console
    },
});

getChildren()

can be used to get a list of its children: getChildren可以得到子元素列表

local.HomePage = instance.Widget.extend({
    start: function() {
        var greeting = new local.GreetingsWidget(this);
        greeting.appendTo(this.$el);
        console.log(this.getChildren()[0].$el);
        // will print "div.oe_petstore_greetings" in the console
    },
});

When overriding the init() method of a widget it is of the utmost importance to pass the parent to the this._super() call, otherwise the relation will not be set up correctly:

当我们在一个组件重写init()方法时,必须记住一个最为重要的事情,必须将组件的parent作为参数调用this._super() ,否则一些函数关系将不能正确体现

local.GreetingsWidget = instance.Widget.extend({
    init: function(parent, name) {
        this._super(parent);
        this.name = name;
    },
});

Finally, if a widget does not have a parent (e.g. because it's the root widget of the application), null can be provided as parent:

最后如果你要创建一个没有父亲的组件(例如应用的根组件)可以用null作为父亲参数传入

new local.GreetingsWidget(null);

Destroying Widgets(销毁组件)

If you can display content to your users, you should also be able to erase it. This is done via the destroy() method:

正如你需要向用户显示内容,你也需要清除内容,你可以用destroy函数

greeting.destroy();

When a widget is destroyed it will first call destroy() on all its children. Then it erases itself from the DOM. If you have set up permanent structures in init() or start() which must be explicitly cleaned up (because the garbage collector will not handle them), you can override destroy().

当一个部件被销毁,它会先调用所有子部件的  destroy() 。然后,它在 DOM中清除自己。通过部件隶属关系的递归调用,避免了内存泄漏,这对容易产生内存泄露的大型 JavaScript 应用程序来说是非常有用的。

未完待续。。。。。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值