五、组件和钩子
组件和钩子是来自Owl组件系统的思想。钩子是分解代码的一种方法,它的存在取决于生命周期,是一种在组件中注入特性的可组合/功能性方法,它们可以被视为一种mixin。
function useCurrentTime() {
const state = useState({ now: new Date() });
const update = () => state.now = new Date();
let timer;
onWillStart(() => timer = setInterval(update, 1000));
onWillUnmount(() => clearInterval(timer));
return state;
}
六、context(上下文)
odoo前端js一个非常重要的概念是context,可以为方法调用或rpc传输数据,可以让系统的其他部分接收和使用这些数据,从某种意义上说,它像是一个到处传播的数据信息包,在很多时候它是非常有用的,例如让ODOO服务知道一个模型的RPC来自于一个特定的表单视图,或者 激活/禁用组件的某些功能。
有两种不同的上下文在odoo的web 客户端,一种是user context,另一种是action context,因此,在使用context时应该小心,因为它可能有不同含义。
注意:不要过度使用上下文,许多问题可以在不修改上下文的情况下以标准方式解决。
1、User Context
用户上下文是一个小对象,包含与当前用户相关的各种信息。它可以通过用户服务获得。
class MyComponent extends Component {
setup() {
const user = useService("user");
console.log(user.context);
}
}
包含如下信息:
名称 | 类型 | 描述 |
allowed_company_ids | number[] | 多公司列表 |
lang | string | 语言,如en_us |
tz | string | 时区 |
在实战中,, orm 服务会自动为每个需要它的地方自动填加user context ,这就是为什么不需要每次都import导入。 |
2、Action Context
ir.actions.act_window 和 ir.actions.client 支持一个带参数的上下文字段(见下行).这个字段是CHAR(字符)类型. 每当在web客户端中加载相应的操作时,此上下文字段将作为对象进行评估,并提供给与该操作对应的组件.
<field name="context">{'search_default_customer': 1}</field>
它可以以许多不同的方式使用。例如,视图将Action Context添加到向服务器发出的每个请求中,另一个重要用途是默认情况下激活一些搜索过滤器,见上行。
有时,当我们手动执行新操作时,可以扩展 action context. 通过 additional_context 参数完成.
// in setup
let actionService = useService("action");
// in some event handler
actionService.doAction("addon_name.something", {
additional_context:{
default_period_id: defaultPeriodId
}
});
在这个例子中, addon_name.something 将被加载, 并且它的上下文用default_period_id 进行扩展. 这是一个非常重要的用例,允许开发人员通过向下一个操作提供一些信息来将操作贯通。
七、python解释器
Odoo框架具有内置的小型python解释器,可以计算一些小型的python表达式,这很重要,因为视图数据已经被修改,这些数据也需要在浏览器端同步更新。
例如:
import { evaluateExpr } from "@web/core/py_js/py";
evaluateExpr("1 + 2*{'a': 1}.get('b', 54) + v", { v: 33 }); // returns 142
py javascript 代码扩展出 5 个功能:
八、domain域
Odoo中的域表示一组与某些特定条件匹配的记录, 通常表示为一组条件列表 (或者是前缀操作符: |, & or ! )或者是字符串表达式,不必很标准化(如有必要,可以使用&运算符),例如:
// 条件列表
[]
[["a", "=", 3]]
[["a", "=", 1], ["b", "=", 2], ["c", "=", 3]]
["&", "&", ["a", "=", 1], ["b", "=", 2], ["c", "=", 3]]
["&", "!", ["a", "=", 1], "|", ["a", "=", 2], ["a", "=", 3]]
// 字符串表达式
"[('some_file', '>', a)]"
"[('date','>=', (context_today() - datetime.timedelta(days=30)).strftime('%Y-%m-%d'))]"
"[('date', '!=', False)]"
字符串表达式的功能要强于列表表达式,但无论怎样,操作字符串表达式比条件列表更困难,也更复杂。
因为domain在前端非常重要,odoo提供了一个domain类:
new Domain([["a", "=", 3]]).contains({ a: 3 }) // true
const domain = new Domain(["&", "&", ["a", "=", 1], ["b", "=", 2], ["c", "=", 3]]);
domain.contains({ a: 1, b: 2, c: 3 }); // true
domain.contains({ a: -1, b: 2, c: 3 }); // false
// next expression returns ["|", ("a", "=", 1), ("b", "<=", 3)]
Domain.or([[["a", "=", 1]], "[('b', '<=', 3)]"]).toString();
domain类描述:
new Domain([('a', '>', b)]
).toList({ b:3 }); // [[‘a’, ‘>’, 3]]
domain类提供了4种常用的表态方法:
// ["&", ("a", "=", 1), ("uid", "<=", uid)]
Domain.and([[["a", "=", 1]], "[('uid', '<=', uid)]"]).toString();
// ["|", ("a", "=", 1), ("uid", "<=", uid)]
Domain.or([[["a", "=", 1]], "[('uid', '<=', uid)]"]).toString();
// ["!", ("a", "=", 1)]
Domain.not([["a", "=", 1]]).toString();
// ["&", ("a", "=", 1), ("uid", "<=", uid)]
Domain.combine([[["a", "=", 1]], "[('uid', '<=', uid)]"], "AND").toString();
九、bus 消息
web client环境对象包括一个bus事件,其目的是使系统的各个部分能够正确地相互协调,而不耦合它们, env.bus 是一个 owl EventBus,它用于公共事件。
// for example, in some service code:
env.bus.on("WEB_CLIENT_READY", null, doSomething);
以下是可bus上触发的事件列表:
信息 | 加载 | 触发 |
ACTION_MANAGER:UI-UPDATED | 什么类型的界面会被更新 (‘current’, ‘new’ or ‘fullscreen’) | 已完成向动作管理器呈现请求的动作 |
ACTION_MANAGER:UPDATE | 下一个渲染信息 | 动作管理器已完成下一个接口的计算 |
MENUS:APP-CHANGED | none | 菜单服务的当前应用程序已更改 |
ROUTE_CHANGE | none | 当url更改 |
RPC:REQUEST | rpc id | rpc请求发生时 |
RPC:RESPONSE | rpc id | rpc请求完成时 |
WEB_CLIENT_READY | none | 当web_client挂载时 |
FOCUS-VIEW | none | 主视图将关注它自身 |
CLEAR-CACHES | none | 应清除所有内部缓存 |
CLEAR-UNCOMMITTED-CHANGES | 功能列表 | 所有未提交更改的视图都应该清除它们,并在列表中推送回调 |
十、浏览器对象 | ||
javascript 框架还提供了一个特殊对象browser,该对象提供对许多浏览器 API 的访问,像location例、localStorage 或setTimeout. 以下是如何使用该 browser.setTimeout功能: |
import { browser } from "@web/core/browser/browser";
// somewhere in code
browser.setTimeout(someFunction, 1000);
例如:
出于测试目的,它很有趣也很有用:通过在测试期间模拟相关函数,可以轻松测试使用浏览器对象的所有代码。
它包含如下内容:
addEventListener
cancelAnimationFrame
clearInterval
clearTimeout
console
Date
fetch
history
localStorage
location
navigator
open
random
removeEventListener
requestAnimationFrame
sessionStorage
setInterval
setTimeout
XMLHttpRequest
十一:DEBUG模式
Odoo DEBUG模式有两种作用:
debug=1或debug=true
debug=assets
debug=tests
1、显示一些附加的功能
2、提供一些附加的工具帮助开发者调试ODOO接口.
The debug mode is described by a string. An empty string means that the debug mode is not active. Otherwise, it is active. If the string contains assets or tests, then the corresponding specific sub modes are activated (see below). Both modes can be active at the same time, for example with the string assets,tests.
DEBUG模式是用一个字符串来表示的,空字符串意味着DEBUG模式没有被激活,如果字符串含有assets或tests,那么说明对应的调试模式被激活了。如果同时出现assets,tests,则表示两种模式同时被激活。
debug模式的当前值可以通过env.debug读取。
提示:
为使菜单、字段或视图只显示在DEBUG模式下,应该将它们的组别设置为:base.group_no_one
<field name="fname" groups="base.group_no_one"/>
Assets 模式
debug=assets 子模式对于调试 javascript 代码是非常有用的: 一旦起用,资产包放开, 并生成source-maps.
Tests 模式
如果启用,该tests模式对于功能导览很有用。