Odoo 13开发者文档:Javascript速查

Odoo Alan 4年前 (2019-12-29) 7418次浏览 0个评论 扫描二维码
本文来自Odoo 13官方文档之开发者文档系列文章
在JavaScript和Odoo中有很多种解决问题的方式。但 Odoo框架的设计是具有可扩展性的 (这一个巨大的约束),而很多常见的问题有漂亮标准方案。标准方案可能具有易于 Odoo 开发者理解的优势,在 Odoo 修改时可保持继续有效。本文档尝试讲解我们可以解决这些问题的方式。注意这不一个手册。只是一个随机集合,或讲解了如何在某些情况下进行处理。首先,记住通过JS自定义odoo的第一条规则是:尽量在python中解决。 这看起来很奇怪,但这个python框架极具扩展性,很多行为只需通过对xml或python.进行少量修改即可实现。 这通常会比操作 JS 的维护成本更低:

  • JS框架会倾向于修改是多内容,因此 JS代码需要进行更频繁的更新
  • 如需与服务端通讯并适当集成javascript 框架实现自定义行为经常会更为复杂。有很多由框架处理的小细节的自定义代码也需要重复编写。例如,响应式、更新 URL 或无闪烁显示数据。

这可能是很常见的用例:我们希望在表单视图中以非常具体的(可能取决于业务)方式显示一些信息。 例如,假定我们希望根据一些业务条件来修改文本的颜色。

这可通过三个步骤来实现:新建一个组件、在字段仓库中注册它,然后在表单视图中添加组件到该字段中

  • 新建组件:
    可通过继承组件来实现:

  • 在字段仓库中注册它:
    网页客户端需要知道组件名称和其实际类之间的映射。这通过仓库完成:

  • 向表单视图添加该组件:

    注意只有表单、列表和看板视图使用这种字段组件仓库。这些视图紧密集成,因为列表和看板视图可以在表单视图中出现。

另一种用例是我们希望修改已有字段组件。例如,odoo中的voip插件需要修改FieldPhone组件来添加对voip易于调用给定号码的可能性。这通过包含FieldPhone组件来实现,因此无需修改已有表单视图。

字段组件 (AbstractField的实例(子类 ))像每个其它组件一样,因此它们可以打猴子补丁。类似下面这样:

注意这里无需添加组件到仓库中,因其已进行了注册。

另一个常见用例是需要通过用户界面自定义一些元素。例如,在 home 菜单中添加消息。这种情况下的常用处理还是包含组件。这是实现它的唯一方式,因为对这些组件没有仓库。

通常通过下面这样的代码实现:

新建视图是一个更高级的话题。这篇速查仅能重点介绍一些很可能会做的步骤 (排序无先后):

  • ir.ui.viewtype字段中新增一种视图类型:
  • ir.actions.act_window.viewview_mode字段中新建视图类型:
  • (在JavaScript中)创建4个组成视图的主要部分:
    我们需要一个视图(AbstractView的子类,这是工厂类),一个渲染器(来自 AbstractRenderer),一个控制器 (来看AbstractController) 以及一个模型 (来自 AbstractModel)。我推荐通过简单继承超类来开始:

  • 在仓库中添加视图:
    和平常一样,视图类型和实际类之间的映射需要进行更新:

  • 实现4个主要类:
    View类需要解析 arch字段并设置其它3个类。 Renderer 负责在用户界面中展示数据, Model 用于和服务端对话、加载数据并处理数据。Controller 用于协调、与网页客户端对话, …
  • 在数据库中创建一些视图:

假定我们需要创建一个通用视图的自定义版本。例如,在上方面带有一些额外类似ribbon的看板视图(来显示一些具体自定义信息)。在这种情况下,它可通过3个步骤来实现:继承看板视图(可能还表示继承 控制器/渲染器及/或模型),然后在视图仓库中注册视图,并且最终在看板框架中使用视图 (具体的示例是helpdesk仪表盘)。

  • 继承视图:
    以下是其可能会有的样子:

  • 将其添加到视图仓库中:
    和平常一样,我们需要告知网页客户端视图名称和实际类之间的映射。

  • 在实际视图中使用它:
    现在我们需要告知网页客户端指定的 ir.ui.view需要使用我们的新类。注意这是一个网页客户端的具体考虑。从服务端的视角来看,我们还是对应看板视图。这么做的相应方式是通过对框架的根节点使用特殊属性js_class(某一天会被重命名为 widget,因为这个名称不够好) :

有关promise的良好和完整介绍,请参阅这篇优质文章 https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/async%20%26%20performance/ch3.md

  • 将常量转换 promise
    Promise有两个静态函数根据常量分别创建已完成(resolved)和已失败(rejected)的promise:

  • 基于已有的异步代码
    假设在函数你必须执行rpc,在已对this完成设置结果时。this._rpc 是一个返回Promise的函数。

  • 对于基于回调的函数
    假定你在使用一个接收在完成时调用的回调作为参数的 this.close 函数。再假设你在一个方法中执行它且该方法必须在关闭完成时返回一个promise。

    • 第2行: 我们将 this 保存到一个变量中,这样在内部函数中,我们可以访问该作用域来作为组件。
    • 第3行: 我们创建并返回了一个新的promise。promise的构造函数接收一个函数作为参数。该函数本身有两个函数,这里我们称之为 resolve 和 reject
      • resolve 是一个在调用时将promise置为resolved状态的函数。
      • reject 是一个在调用时将promise置为rejected状态的函数。这里我们不使用reject,可以将其省略。
    • 第4行: 我们调用关闭对象的函数。它接收一个函数作为参数(回调)并在resolve已是一个函数时发生,因此可以直接进行传递。进一步说明,我们可以这样写:
  • 创建一个 promise生成器 (按序分别调用不同的promise并等待最一个promise)
    假定你需要对数组进行循环,按顺序执行操作并在最后一个操作完成时返回一个 promise。

    通过这种方式,我所返回的 promise就是最后那个promise。

  • 创建一个promise,然后在其定义的作用域外部解析它(反模式)
  • 等待数个Promise
    如果你有多个需要等待的promise, 可以将它们转化为单个promise,它将在promise所有使用Promise.all(arrayOfPromises)进行解析时解析。

  • 等待promise链中的一部分,另一部分不进行等待
    If you have an asynchronous process that you want to wait to do something, but you also want to return to the caller before that something is done.

  • in general in promises
    总体思想是promise在控制流中不应失败,仅在出现错误时失败。在这种情况下,promise应当有多个已完成状态,例如在then处理器的状态码及promise链最终的单个 catch 处理器。

  • Odoo中具体情况
    在Odoo,中,我们对控制流使用promise的失败状态,类似互拆体和web.concurrency中定义的其它并发原语。出于业务原因我们还希望执行 catch,但不是在promise或处理器的定义中有代码错误时。因此,我们引入 了guardedCatch的概念。它的调用类似 catch ,但不在失败的原因为错误时

  • 在测试中使用promises
    在测试代码中,我们支持Javascript的最新版本, 包含async 和 await和这样的原语。 这样 promise 的使用和等待都非常容易。大部分帮助方法还返回 promise (通过标记为async 或通过直接返回一个promise)。

    可以目的地到,更好的形式是使用 async/await ,因其更为清晰、编写更简短。

喜欢 (4)
[]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址