【Odoo16前端源码分析】xml模板的加载
一、模板内容的来源
情况A,组件类的template属性,比如ActionContainer.template
/* odoo/addons/web/static/src/webclient/actions/action_container.js */export class ActionContainer extends Component {setup() {..}
}
..
ActionContainer.template = xml`<t t-name="web.ActionContainer"><div class="o_action_manager"><t t-if="info.Component" t-component="info.Component" className="'o_action'" t-props="info.componentProps" t-key="info.id"/></div></t>`;
情况B,组件类的同名xml文件,比如webclient.xml
<!-- /* odoo/addons/web/static/src/webclient/webclient.xml */ --><?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve"><t t-name="web.WebClient" owl="1"><t t-if="!state.fullscreen"><NavBar/></t><ActionContainer/><MainComponentsContainer/></t></templates>
二、存放模板内容的变量
情况A,存放在owl.js文件中的globalTemplates变量中
/* odoo/addons/web/static/lib/owl/owl.js */const globalTemplates = {};
function xml(...args) {const name = `__template__${xml.nextId++}`;const value = String.raw(...args);globalTemplates[name] = value;return name;
}
xml.nextId = 1;
情况B,通过app.addTemplates方法,将xml保存在TemplateSet的rawTemplates中,步骤如下
1 将各种xml文件打包到一个字符串templates中,然后调用loadXML方法处理templates
/* web.assets_backend.bundle.xml文件是由后台动态打包生成的 *//******************************************** Templates ********************************************/
odoo.define('web.assets_backend.bundle.xml', function(require) {'use strict';const {loadXML} = require('@web/core/assets');const templates = `<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
// xml文件的内容,做了省略处理
..
<t t-name="web.WebClient" owl="1"><t t-if="!state.fullscreen"><NavBar/></t><ActionContainer/><MainComponentsContainer/></t>
..
</templates>`;return loadXML(templates);
});
2 设置app实例变量(注意:这里的app就是全局开始创建的唯一app实例)
/* odoo/addons/web/static/src/start.js */export async function startWebClient(Webclient) {..setLoadXmlDefaultApp(app);..
}
3 loadXML方法将templates中的xml文本,按照t-name属性提取出来,以key/value形式保存
/* odoo/addons/web/static/src/core/assets.js */let defaultApp;
/*** Loads the given xml template.** @param {string} xml the string defining the templates* @param {App} [app=defaultApp] optional owl App instance (default value* can be changed with setLoadXmlDefaultApp method)* @returns {Promise<true>} resolved when the template xml has been loaded*/
export const _loadXML = (assets.loadXML = function loadXML(xml, app = defaultApp) {const doc = new DOMParser().parseFromString(xml, "text/xml");if (doc.querySelector("parsererror")) {throw doc.querySelector("parsererror div").textContent.split(":")[0];}for (const element of doc.querySelectorAll("templates > [t-name][owl]")) {element.removeAttribute("owl");const name = element.getAttribute("t-name");const previous = templates.querySelector(`[t-name="${name}"]`);if (previous) {console.debug("Override template: " + name);previous.replaceWith(element);} else {templates.documentElement.appendChild(element);}}if (app || defaultApp) {console.debug("Add templates in Owl app.");app.addTemplates(templates, app || defaultApp);} else {console.debug("Add templates on window Owl container.");}
});
/*** Update the default app to load templates.** @param {App} app owl App instance*/
export function setLoadXmlDefaultApp(app) {defaultApp = app;
}
三、将globalTemplates作为原型来创建this.rawTemplates属性,所以以后通过rawTemplates就能访问globalTemplates(前提是rawTemplates中没有要访问的属性时,才会访问globalTemplates,这是JS的原型链原理)
/* odoo/addons/web/static/lib/owl/owl.js */class TemplateSet {constructor(config = {}) {this.rawTemplates = Object.create(globalTemplates);this.templates = {};..if (config.templates) {this.addTemplates(config.templates);}}..
}
因为App继承TemplateSet,并且App没有定义rawTemplates属性,所以app.addTemplates操作的是TemplateSet的rawTemplates
四、后面其他功能通过app.rawTemplates获取需要的模板
相关文章:
【Odoo16前端源码分析】xml模板的加载
一、模板内容的来源 情况A,组件类的template属性,比如ActionContainer.template /* odoo/addons/web/static/src/webclient/actions/action_container.js */export class ActionContainer extends Component {setup() {..} } .. ActionContainer.templ…...
Open3D (C++) 计算矩阵的广义逆
目录 一、算法原理1、广义逆2、计算过程二、代码实现三、结果展示四、参考链接本文由CSDN点云侠原创,原文链接。爬虫网站自重,把自己当个人,爬些不完整的误导别人有意思吗???? 一、算法原理 1、广义逆 非方阵不存在逆,但是存在广义逆(伪逆)。对于一个矩阵...
11.物联网操作系统内存管理
一。STM32编译过程及程序组成 STM32编译过程 程序的组成、存储与运行 MDK生成的主要文件分析 1.STM32编译过程 1.源文件(Source code)--》目标文件(Object code) .c(C语言)通过armcc生成.o,.s(汇编&…...
举办活动发布会,如何得到媒体支持?
传媒如春雨,润物细无声,大家好,我是51媒体网胡老师。 举办活动发布会并得到媒体报道的支持是一个关键的宣传和推广手段。以下是一些建议,帮助你增加吸引媒体关注和报道的机会: 1. 策划新闻价值:确保你的发…...
1139 First Contact(unique函数,string.substr()函数)
PTA | 程序设计类实验辅助教学平台 用map套个set来实现邻接表(排序都免了) #include<bits/stdc.h> using namespace std; int n,m,k; string a,b; map<string,set<string>>mp; int main() {cin.tie(0);cin >> n >> m;fo…...
Python元编程-装饰器介绍、使用
目录 一、Python元编程装饰器介绍 二、装饰器使用 1. 实现认证和授权功能 2.实现缓存功能 3.实现日志输出功能 三、附录 1. logging.basicConfig介绍 2. 精确到毫秒,打印时间 方法一:使用datetime 方法二:使用time 一、Python元编程…...
python进程池的使用
进程池的创建 apply() apply()方法用于向进程池提交一个任务,并等待任务完成并返回结果。 apply_async() apply_async()方法用于向进程池提交一个异步任务(即无需等待任务完成),将任务加入到进程池的队列里,并立即…...
Dockerfile构建lamp镜像
1、构建目录 [rootdocker ~]# mkdir compose_lamp [rootdocker ~]# cd compose_lamp/ 2、编写Docekerfile [rootdocker compose_lamp]# vim Dockerfile #基础镜像 FROM centos:7#维护该镜像的用户信息 MAINTAINER Crushlinux <crushlinux163.com>#安装httpd RUN yum -…...
LeetCode724. 寻找数组的中心下标
题干 给你一个整数数组 nums ,请计算数组的 中心下标 。 数组 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。 如果中心下标位于数组最左端,那么左侧数之和视为 0 ,因为在下标的左侧不存在元素。…...
【云计算 | Docker】Docker容器后台运行不了?entrypoint在作妖?
1. 问题 使用镜像alpine起个容器,使其保持后台运行,正常情况有如下的效果,可以发现容器保持运行状态。 [rootk8s-master helloWorld]# docker run -dit docker.io/alpine /bin/sh 8d39d7579d5e4f1a560aef16ba57ab5cae2506ea9105e21cbc0634…...
DAY02_Spring第三方资源配置管理Spring容器Spring注解开发Spring整合Mybatis和Junit
目录 一 第三方资源配置管理1 管理DataSource连接池对象问题导入1.1 管理Druid连接池1.2 管理c3p0连接池 2 加载properties属性文件问题导入2.1 基本用法2.2 配置不加载系统属性2.3 加载properties文件写法 二 Spring容器1 Spring核心容器介绍问题导入1.1 创建容器1.2 获取bean…...
烘焙小程序蛋糕店烘焙店源码点心店小程序源码
本系统开发使用JAVA技术栈开发 使用uniapp技术栈 支持微信小程序 ,对接打印机,对接第三方同城跑腿平台 用户端使用:uniapp 管理端使用:vueelementui 后台服务使用:springbootjpa...
HarmonyOS 开发基础(五)对用户名做点啥
一、实现用户名检验 条件渲染 、生命周期 1.规定用户名长度 2.限定使用的数字及字母(涉及正则表达) // 导出方式直接从文件夹 import MyInput from "../common/commons/myInput" Entry Component /* 组件可以基于struct实现,组件…...
【前端】搭建Vue3框架
目录 一、搭建准备二、node.js安装1、下载并安装2、配置默认安装目录和缓存日志目录①、创建默认安装目录和缓存日志目录(我的node.js目录在D盘,所以直接在node.js文件夹下创建)②、执行命令,配置默认安装目录和缓存日志目录到刚才…...
Opencv-C++笔记 (15) : 像素重映射 与 图像扭曲
文章目录 一、重映射简介二、图像扭曲 一、重映射简介 重映射,就是把一幅图像中某位置的像素放置到另一图像指定位置的过程。即: 在重映射过程中,图像的大小也可以同时发生改变。此时像素与像素之间的关系就不是一一对应关系,因…...
【Java】UWB高精度工业人员安全定位系统源码
基于VueSpring boot前后端分离架构开发的一套UWB技术高精度定位系统源码。 UWB高精度人员定位系统提供实时定位、电子围栏、轨迹回放等基础功能以及各种拓展功能,用户可根据实际需要任意选择搭配拓展功能。该系统简易部署,方便使用,实时响应。UWB高精度定…...
文本NLP噪音预处理(加拼写检查)
最近总结修改了下预处理方法,记录下 首先download需要的依赖 pip install pyenchantpip install nltk pyenchant 是用来检测拼写正确的,如果你的文本里面可能包含非正确拼写的单词,那就忽略它,nltk用来做分词的。 python -m nlt…...
[Docker实现测试部署CI/CD----自由风格的CI操作[最终架构](5)]
目录 11、自由风格的CI操作(最终)Jenkins容器化实现方案修改 docker.sock 权限修改 Jenkins 启动命令后重启 Jenkins构建镜像推送到Harbor修改 daemon.json 文件Jenkins 删除构建后操作Jenkins 添加 shell 命令重新构建 Jenkins通知目标服务器拉取镜像目…...
纯JS+Vue实现一个仪表盘
在使用canvas的时候发现数值变化,每次都要重新渲染,值都从0开始,这和我的需求冲突。 1. 先绘制基本的圆环背景,利用border-color和border-radius将正方形变成基本的圆环。 <div class"circle"><div class&qu…...
标定(内参、外参)
在计算机视觉中,特别是在相机标定和立体视觉领域,内参(intrinsic parameters)和外参(extrinsic parameters)是非常重要的概念。它们与相机的几何属性和姿态有关。 内参(Intrinsic Parameters&am…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...
