第四章 组件

WebClient

我们在经典的WebClient世界中已经对它非常熟悉了,但是从odoo开始使用OWL开始重构WebClient时,我们就注定了要以一种新的思维方式来认识它的新面孔。

我们先来看一下WebClient的架构图:

加载

WebClient是加载到DOM的body标签的主要组件,它通过startWebClient方法实现加载的:

const root = await mount(Webclient, { env, target: document.body, position: "self" });

组成

WebClient.components = {
    ActionContainer,
    NavBar,
    NotUpdatable,
    MainComponentsContainer,
};
WebClient.template = "web.WebClient";

由WebClient的组件定义可以看出,WebClient主要由以下四个组件组成:

  • NavBar: Odoo顶端的导航栏
  • ActionContainer: 动作容器
  • MainComponentsContainer: 组件所在的容器
  • NotUpdatable: 重载了shouldUpdate方法并返回false值的基本包装组件,用于创建静态组件

初始化

setup() {
    this.menuService = useService("menu");
    this.actionService = useService("action");
    this.title = useService("title");
    this.router = useService("router");
    this.user = useService("user");
    ...
    if (this.env.debug) {
        registry.category("systray").add(
            "web.debug_mode_menu",
            {
                Component: DebugMenu,
            },
            { sequence: 100 }
        );
    }
    this.localization = localization;
    this.title.setParts({ zopenerp: "Odoo" });

WebClient在初始化的过程中,内置了一下几种服务以供后续使用:

  • menuService: 菜单服务
  • actionService: 动作服务
  • title: 标题服务
  • router: 路由服务
  • user: 用户服务

如果用户开启了开发这模式,那么WebClient将显示debug图标,并加载DebugMenu组件。

WebClient使用title服务设置了系统服务名称为"Odoo",并使用了关键字zopenerp。后面我们会介绍如果使用重载机制将系统标题更换为我们自定义的标题。

WebClient初始化的过程中还加载了若干总线,来完成事件响应。

挂载

WebClient挂载到DOM中之后就会触发WEB_CLIENT_READY事件,以通知其他组件开始工作。

Patch组件

在经典的WC实现中如果我们想要通过重载某个模块的的某个方法,可以使用include方法来实现, 到了OWL的世界中,也存在同样的方法, 即Patch方法. 下面我们就来看一下, 如何使用patch方法对一个组件进行重载.

首先patch方法位于web模块的utils包中,因此我们在我们的代码里中需要进行导入:

import { patch } from "@web/core/utils/patch";

patch方法接受四个参数:

  • obj {object}: 需要被patch的对象
  • patchName {string}: patch的名称
  • patchValue {object}: patch的值
  • pure {boolean}: 可选options的参数

这里我们以Mommy Base模块中, 设置系统标题的功能给大家展示如何patchWebClient对象. Mommy Base模块是笔者自己开发的一个模块, 主要用来对系统进行一些初始的个性化设置和增强功能. 这里我们要介绍的是它的设置系统标题功能, 我们都知道Odoo在安装完成后,默认显示的标题是odoo.

现在,我们想要把这个标题改掉,改成可以用户自定义的模式.通过对源码的分析,我们了解到,要想实现对系统标题的修改,就需要使用title服务的setParts方法, 想要获取到用户设置的标题,就需要使用rpc服务, 最后,我们在WebClient的初始化方法中对原有的标题进行修改.

patch(WebClient.prototype, "_webClient", {
    async setup() {
        this._super(...arguments);
        let data = await this.env.services.rpc("/web/dataset/call_kw/ir.config_parameter/get_param", {
            model: "ir.config_parameter",
            method: "get_param",
            args: ["mommy.title"],
            kwargs: {}
        })
        this.title.setParts({ zopenerp: data })
    }
});

odoo的系统标题使用了一个比较奇怪的关键字zopenerp, 原因也比较简单,就是为了方便查找..

参考资料

results matching ""

    No results matching ""