第八章 环境变量

OWL中的环境变量封装了几个核心的功能,以供组件使用。

环境变量的核心功能

export function makeEnv() {
    return {
        qweb: new owl.QWeb(),
        bus: new owl.core.EventBus(),
        services: {},
        debug: odoo.debug,
        _t: () => {
            throw new Error("Translations are not ready yet. Maybe use _lt instead?");
        },
        get isSmall() {
            throw new Error("UI service not initialized!");
        },
    };
}

环境变量不是一个单独的对象,它本质上是一个封装了几个内置对象的字典。其内部的主要组成部分有如下几个:

  • qweb: qweb组件
  • bus: 事件总线组件
  • services: 所有已组册的服务字典
  • debug: 是否调试模式

环境变量的加载

环境变量对外提供服务,是通过makeEnv方法返回一个环境变量的字典而完成的。

我们之前在WebClient部分提到,系统通过startWebClient方法启动WebClient的初始化,而环境变量在WebClient启动的时候也进行了初始化,并将其包含的所以已注册的服务进行启动。

// setup environment
const env = makeEnv();
const [, templates] = await Promise.all([
    startServices(env),
    odoo.loadTemplatesPromise.then(processTemplates),
]);
env.qweb.addTemplates(templates);
...
const root = await mount(Webclient, { env, target: document.body, position: "self" });

因此,我们在WebClient中可以直接使用如下的方式使用已经注册的服务:

this.env.service.rpc(...);

startServices

与环境变量一同定义的还有一个startServices方法,该方法的作用是启动注册中心所有已经注册的服务,并保证每个服务的依赖已经正确的加载。

WebClient的启动过程便使用了该方法进行服务启动。

事件总线

事件总线(Event Bus)是一个用于在不同组件之间传递事件和数据的机制。它允许组件之间进行通信,而不需要直接引用彼此。这种松耦合的设计使得系统更加模块化和可维护。

事件总线的有下面几种作用:

  • 事件触发:组件可以通过事件总线触发事件。触发事件时,可以附带一些数据,供其他组件使用。

  • 事件订阅:组件可以订阅特定的事件。当事件发生时,订阅该事件的组件会收到通知,并可以执行相应的操作。

  • 事件处理:订阅事件的组件可以定义事件处理函数,以处理接收到的事件和数据

事件触发

trigger方法用来触发事件

this.bus.trigger("demo:onClick");

上面的代码即触发了一个demo组件的onClick事件。

事件订阅

addEventListener方法用来定义一个自定义事件。

this.bus.addEventListener("demo:onClick", this.onClick.bind(this));

上面的代码就定义了一个demo组件的onClick事件,并将组件的onClick方法绑定到了此事件中,作为事件的处理方法。

事件处理

在事件的订阅方法的第二个参数数即传入了事件的处理函数。

async onClick() {
    ...
}

借助事件总线,我们可以实现跨组件的事件监听与调用。下面是一个完整的事件总线调用示例:

import { Component, useState } from "@odoo/owl";

export class ComponentA extends Component {
    static template = "my_module.ComponentA";
    setup() {
        this.state = useState({ value: 0 });
    }
    increment() {
        this.state.value++;
        this.env.bus.trigger('state-changed', { value: this.state.value });
    }
}

export class ComponentB extends Component {
    static template = "my_module.ComponentB";
    setup() {
        this.state = useState({ value: 0 });
        this.env.bus.addEventListener('state-changed', this, this.updateState);
    }
    updateState(event) {
        this.state.value = event.detail.value;
    }
}

16.0及之前版本事件订阅使用的是on方法

总结

关于环境变量的内容并不是很长,因为环境变量其本身的逻辑并不复杂,只是它的作用很重要,我们只有理解了它的作用,在阅读其他代码的时候才不会迷茫。

results matching ""

    No results matching ""