第八章 环境变量
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方法
总结
关于环境变量的内容并不是很长,因为环境变量其本身的逻辑并不复杂,只是它的作用很重要,我们只有理解了它的作用,在阅读其他代码的时候才不会迷茫。