这是view系列的第四篇文章,专门介绍View组件。
作为一个Component,它总共包含js、css、xml三个标准文件,当然最重要的是view.js
首先在setup函数中对传入的参数props做了各种校验,然后扩展了subenv
useSubEnv({
keepLast: new KeepLast(),
config: {
...getDefaultConfig(),
...this.env.config,
},
...Object.fromEntries(
CALLBACK_RECORDER_NAMES.map((name) => [name, this.props[name] || null])
),
});
这个env只会传递给子组件。
然后调用了loadViews函数
onWillStart(() => this.loadView(this.props));
在loadViews函数中,调用了viewService,然后viewService从后端加载了view(有缓存机制)
const result = await this.viewService.loadViews(
{ context, resModel, views },
{ actionId: this.env.config.actionId, loadActionMenus, loadIrFilters }
);
根据从后端返回的xml结构,代码会将xml解析成一个对象,并读取其中的属性,
下面这段代码中,读取了js_class属性,并将它设置为subType,如果设置了这个属性,系统会从views注册表中读取相关的描述符来代替默认的描述符。
描述符是一结构体(字典),我们经常用来对视图进行扩展,定义号之后需要在viewRegistry中注册它,这里才能嗲用到。
还有banner_route属性
sample属性不知道是干嘛的
const archXmlDoc = parseXML(arch.replace(/ /g, nbsp));
let subType = archXmlDoc.getAttribute("js_class");
const bannerRoute = archXmlDoc.getAttribute("banner_route");
const sample = archXmlDoc.getAttribute("sample");
const className = computeViewClassName(type, archXmlDoc, [
"o_view_controller",
...(props.className || "").split(" "),
]);
// determine ViewClass to instantiate (if not already done)
if (subType) {
if (viewRegistry.contains(subType)) {
descr = viewRegistry.get(subType);
} else {
subType = null;
}
}
后面的代码就是根据返回值在组装viewProps
const viewProps = {
info,
arch: archXmlDoc,
fields,
relatedModels,
resModel,
useSampleModel: false,
className,
};
然后是准备WithSearch 组件的属性
const finalProps = descr.props ? descr.props(viewProps, descr, this.env.config) : viewProps;
// prepare the WithSearch component props
this.Controller = descr.Controller;
this.componentProps = finalProps;
this.withSearchProps = {
...toRaw(props),
hideCustomGroupBy: props.hideCustomGroupBy || descr.hideCustomGroupBy,
searchMenuTypes,
SearchModel: descr.SearchModel,
};
看看结尾的部分:
View.template = "web.View";
View.components = { WithSearch };
View.defaultProps = {
display: {},
context: {},
loadActionMenus: false,
loadIrFilters: false,
className: "",
};
View.props = {
"*": true,
};
View.searchMenuTypes = ["filter", "groupBy", "favorite"];
看看它的xml模板
<t t-name="web.View">
<WithSearch t-props="withSearchProps" t-slot-scope="search">
<t t-component="Controller"
t-on-click="handleActionLinks"
t-props="componentProps"
context="search.context"
domain="search.domain"
groupBy="search.groupBy"
orderBy="search.orderBy"
comparison="search.comparison"
display="search.display"/>
</WithSearch>
</t>
WithSearch 是一个虚拟组件,它本身不渲染任何东西,里面包括了一个动态组件Controller,这个其实就是各类视图的controller组件。 那render组件呢? 是controller组件的子组件吗? 这个问题留在后面去回答。文章来源:https://www.toymoban.com/news/detail-763815.html
总结一波:
view组件通过viewService后缓存或者后端获取了view的信息,包括id,arch,model等,然后通过一个虚拟组件WithSearch 包裹了一个动态的controller组件,最终显示出来,那么view组件在哪里被调用的呢?这些疑问随着学习的深入我相信终究会找到答案。文章来源地址https://www.toymoban.com/news/detail-763815.html
到了这里,关于odoo17核心概念view4——view.js的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!