Odoo 10 Learnodoo 10 中文文档odoo

odoo V10中文参考手册(八:Javascript)

2017-04-12  本文已影响2452人  XiaoHaiYang

Javascript

Widgets

web.Widget输出class Widget(),是所有可视组件的基类,相当于mvc的view层,提供一系列的处理页面的方法

DOM根元素

Widget()负责的是根DOM下的一部分widget页面,可以通过两个属性来获取widget的DOM:

有两种方法来定义生成DOM根元素:

使用widget

widget的生命周期分三个阶段:

参数:
parent (Widget()) - 新创建的widget的父级,如果某widget没有父级可传null

上述方法接收的参数和对应jquery方法接收的参数一致,会返回一个 deferred延迟执行对象,并赋予三个任务:

1.使用renderElement()来渲染widget的根元素
2.用对应的jquery方法将widget插入到dom中
3.启动widget并将启动的结果返回
Widget.start():当widget被插入到DOM之后异步启动,一般用于异步的rpc调用以获取远端数据用于widget中,完成后需要返回一个deferred对象。在start方法执行完成之前widget的功能不一定是完整的。

与widget销毁相关的函数:

this.alive(this.model.query().all()).then(function (records) {
    // would break if executed after the widget is destroyed, wrapping
    // rpc in alive() prevents execution
    _.each(records, function (record) {
        self.$el.append(self.format(record));
    });
});

参数:
deferred - deferred对象
reject - 默认情况下如rpc调用完成后widget已被销毁的话对应的deferred对象只是被封锁了,如果设置为True的话会将其调用拒绝

获取DOM内容

由于widget负责其DOM元素下的内容,可以用一个简便的方法去获取它DOM元素内的子片段:
Widget.$(selector) 将css选择器应用到widget的根DOM上

this.$(selector);
相当于this.$el.find(selector);

重置DOM根元素

Widget.setElement(element)
将widget的根DOM设置为指定的DOM,参数element需为一个DOM元素或相应的jquery对象

DOM事件处理

widget一般需要在相应页面内响应用户的动作,这需要通过将事件绑定到DOM元素上来实现。

events: {
    'click p.oe_some_class a': 'some_method',
    'change input': function (e) {
        e.stopPropagation();
    }
},

回调函数只会被对应根DOM的匹配子元素触发。如果事件选择器留空的话,该事件是会被自动绑定到widget的根DOM上。

该方法需要与backbone的delegateEvents相兼容

Widget子类

可以通过extend来创建Widget()的子类,并提供了一些抽象方法和具体方法用于使用。

var MyWidget = Widget.extend({
    // 渲染对象时使用的qweb模板
    template: "MyQWebTemplate",
    events: {
        // 事件绑定示例
        'click .my-button': 'handle_click',
    },

    init: function(parent) {
        this._super(parent);
        // 在渲染之前执行的内容
        // initialization
    },
    start: function() {
        var sup = this._super();
        // 渲染初始化逻辑

        // 允许多重deferred对象
        return $.when(
            // 从父类获取异步信号
            sup,
            // 返回自己的异步信号
            this.rpc(/* … */))
    }
});


##使用
// 创建实例
var my_widget = new MyWidget(this);
// 渲染并插入到dom
my_widget.appendTo(".some-div");

##销毁
my_widget.destroy();

开发规范

RPC

为了进行显示和交互,需要使用rpc与odoo服务器通信,odoo提供两种api来处理:

高级别API 直接调用odoo模块

通过Model()来访问odoo的对象方法,通过call方法(来自web.Model)和 query方法(来自web.DataModel)来访问odoo服务器对象

var Users = new Model('res.users');

Users.call('change_password', ['oldpassword', 'newpassword'],
                  {context: some_context}).then(function (result) {
    // do something with change_password result
});
Users.query(['name', 'login', 'user_email', 'signature'])
     .filter([['active', '=', true], ['company_id', '=', main_company]])
     .limit(15)
     .all().then(function (users) {
    // do work with users records
});

query在调用all()first()方法之前是不会实际执行的,这两个方法每次调用都会触发一个rpc请求。可以用来进行实时查询。

class Model(name)

参数:

  1. method (String) 通过rpc调用的模型方法
  2. args (Array<>) 位置匹配的参数列表
  3. kwargs (Object<>) 传递的关键字参数

参数:fields (Array<String>) 搜索时需要获取的字段列表

class odoo.web.Query(fields)

第一部分方法是读取方法,它们使用所调用对象的数据来响应rpc请求

参数: grouping (Array<String>) - 分组列表
返回: Deferred<Array<odoo.web.QueryGroup>> | null

第二部分方法是设置方法,它们会创建一个新Query对象并对相关属性进行扩展或替换

**分组聚合 **
odoo有非常强大的分组运算功能,但是它是递归的,并且第N+1层依赖于第n层所提供的数据,所以当odoo.models.Model.read_group()工作时这个api就不是那么直观。
odoo一般用Query()方法来代替 read_group()方法。

some_query.group_by(['field1', 'field2']).then(function (groups) {
    // do things with the fetched groups
});

该方法可以接受一个字段列表参数、也可以不带参数执行,无参数时直接返回null而不是deferred对象
当分组条件从其他地方来的时候,可以通过两种方法来测试:

var groups;
if (groups = some_query.group_by(gby)) {
    groups.then(function (gs) {
        // groups
    });
}
// no groups
$.when(some_query.group_by(gby)).then(function (groups) {
    if (!groups) {
        // No grouping
    } else {
        // grouping, even if there are no groups (groups
        // itself could be an empty array)
    }
});

成功的情况下group_by返回的结果是一个 QueryGroup()数组

class odoo.web.QueryGroup() 返回分组的属性key,有以下几种
odoo.web.QueryGroup.query([fields...]) 相当于Model.query() ,但只包含当前分组内的记录,返回一个Query对象供后续使用
odoo.web.QueryGroup.subgroups() 返回一个指向当前的子QueryGroup()的数组的deferred对象

底层API:RPC调用python程序

Session()对象(通过web.Session实例化)的rpc方法提供了一个低级别api用来直接调用python程序,该方法接收一个完整URL、一个参数key=>value映射表 作为参数,并将对应获取的结果转换成json格式

session.rpc('/web/dataset/resequence', {
    model: some_model,
    ids: array_of_ids,
    offset: 42
}).then(function (result) {
    // resequence didn't error out
}, function () {
    // an error occured during during call
});

web client

javascript模块系统

从odoo v8开始使用一套跟requirejs类似的js模块系统,它有以下优点:

缺点:

在这种模式下,通过require来导入需要的模块,并且显示声明所输出的对象。

odoo.define('addon_name.service', function (require) {
    var utils = require('web.utils');
    var Model = require('web.Model');

    // do things with utils and Model
    var something_useful = 15;
    return  {
        something_useful: something_useful,
    };
});

上面的代码创建了一个名叫addon_name.service的模块,使用odoo.define函数定义。

odoo.define函数有两个参数:
1.name - 新定义的模块名

2.function - 在里面定义该模块实际包含的内容,接收一个require参数,如果需要输出内容就需要有对应返回,require函数用于获取依赖的模块。

用javascript来导入需要的模块就声明输出内容,web客户端会自动进行加载。模块在文件中定义,一般最好一个文件对应一个模块。模块可以返回一个deferred对象,这样该模块只在deferred执行后才加载,而且模块可以被废弃,并在控制台记录对应信息:

Missing dependencies - 该模块不会出现在页面中,可能是javascript文件不在页面中或模块名有错误

Failed modules - 有javascript错误
Rejected modules - 模块返回的是一个废弃的deferred
Rejected linked modules - 该模块依赖于已废弃的模块
Non loaded modules - 模块所依赖的模块不存在或有错误

Web client结构

还有其他两个文件:tour.js用于tour,compatibility.js用于将旧系统与新系统兼容,在这个文件中每个模块名被输出到全局变量odoo中。理论上模块可以不通过变量odoo使用。

javascript习惯

odoo web client测试

详见:http://www.odoo.com/documentation/10.0/reference/javascript.html#testing-in-odoo-web-client


译自odoo官方文档:http://www.odoo.com/documentation/10.0/reference/javascript.html ,不当之处欢迎批评指正。

内容发布自http://www.jianshu.com/u/6fdae8ec06bc,转载请注明出处

上一篇 下一篇

猜你喜欢

热点阅读