theme详解[三]
# 5. 总结与延伸学习 🚀
在这篇文章中,我们深入探讨了如何利用 theme.json
来优化 Ambari 的 UI
配置,从基本概念到实际操作,涵盖了页面布局的方方面面。通过 theme.json
,开发者可以根据需求定制页面布局,丰富交互体验,并且通过分层展示配置内容,使复杂的配置更加直观。
# 5.1 总结 🎯
- 自定义 UI 样式与布局
我们展示了如何使用
theme.json
灵活定制页面布局,包括布局行列、区块分布、依赖配置等,提升了 UI 的可维护性和交互体验。 - 动态展示逻辑
通过配置
depends-on
和property_value_attributes
等字段,开发者可以根据配置项的状态动态控制 UI 的展示逻辑。 - 代码与实操结合 在文章的后半部分,我们提供了详细的代码解析和实操演示,帮助开发者从实际项目中运用所学内容。
# 5.2 延伸学习 🔍
在进一步学习中,可以从以下几个方面深入探索:
- 自定义组件:学习如何通过扩展
widgets
来创建新的 UI 组件,满足特定的交互需求。 - 配置依赖管理:研究更复杂的依赖管理,结合多层次条件展示,进一步提升页面的交互性和智能化。
- 二次开发与集成:将
theme.json
与其他配置文件结合使用,在实际项目中更好地实现二次开发和系统集成。
# 5.3 源码探索 🚀
在深入研究 Ambari 的页面渲染时,我首先观察了页面加载的逻辑,尤其是如何通过主题(theme)文件控制页面的显示。在此过程中,我发起了一个
HTTP 请求来获取 theme
文件的内容,具体示例如下:
curl 'http://localhost:28080/api/v1/stacks/BIGTOP/versions/3.2.0/services/RANGER/themes?ThemeInfo/default=true&fields=*&_=1728056865519' \
-H 'Accept: application/json, text/javascript, */*; q=0.01' \
-H 'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6' \
-H 'Cache-Control: no-cache' \
-H 'Connection: keep-alive' \
-H 'Content-Type: text/plain' \
-H 'Cookie: _ga=GA1.1.1591965935.1720631763; apt.uid=AP-YFGMCGUNNIFB-2-1726927068139-89959811.0.2.a2e3917a-4f22-4c24-8671-436b74b600a2; _ga_0C4M1PWYZ7=GS1.1.1726929800.18.0.1726929803.0.0.0; _ga_T11SF3WXX2=GS1.1.1726929800.16.0.1726929803.57.0.0; _ga_K2SPJK2C73=GS1.1.1726929800.16.0.1726929803.57.0.0; AMBARISESSIONID=node01gxv4zh4t6d7r1ky20cwkja56p0.node0' \
-H 'Pragma: no-cache' \
-H 'Referer: http://localhost:28080/' \
-H 'Sec-Fetch-Dest: empty' \
-H 'Sec-Fetch-Mode: cors' \
-H 'Sec-Fetch-Site: same-origin' \
-H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 Edg/129.0.0.0' \
-H 'X-Requested-By: X-Requested-By' \
-H 'X-Requested-With: XMLHttpRequest' \
-H 'sec-ch-ua: "Microsoft Edge";v="129", "Not=A?Brand";v="8", "Chromium";v="129"' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'sec-ch-ua-platform: "Windows"'
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
这个请求返回了多个独立的 JSON
文件,每个文件包含服务的特定主题配置,例如 credentials.json
、database.json
、directories.json
和 theme_version_2.json
。这些 JSON 文件用于控制 Ranger 服务在 Ambari UI 中的渲染方式。
# 返回结果解析
在返回结果中,每个模块都可以被细化提取,并分开管理。以下是一个典型的返回结果的结构部分:
{
"href": "http://localhost:28080/api/v1/stacks/BIGTOP/versions/3.2.0/services/RANGER/themes?ThemeInfo/default=true&fields=*&_=1728056865519",
"items": [
{
"href": "http://localhost:28080/api/v1/stacks/BIGTOP/versions/3.2.0/services/RANGER/themes/credentials.json",
"ThemeInfo": {
"default": true,
"file_name": "credentials.json",
"service_name": "RANGER",
"stack_name": "BIGTOP",
"stack_version": "3.2.0",
"theme_data": {
"Theme": {
"name": "credentials",
"configuration": {
"placement": {
"configs": [
{
"config": "ranger-env/admin_username",
"removed": false,
"subsection-name": "subsection-ranger-admin-credential"
}
],
"configuration-layout": "credentials"
},
"widgets": [],
"layouts": []
}
}
}
}
},
{
"href": "http://localhost:28080/api/v1/stacks/BIGTOP/versions/3.2.0/services/RANGER/themes/database.json",
"ThemeInfo": {
"default": true,
"file_name": "database.json",
"service_name": "RANGER",
"stack_name": "BIGTOP",
"stack_version": "3.2.0",
"theme_data": {
"Theme": {
"name": "database",
"configuration": {
}
}
}
}
},
{
"href": "http://localhost:28080/api/v1/stacks/BIGTOP/versions/3.2.0/services/RANGER/themes/directories.json",
"ThemeInfo": {
"default": true,
"file_name": "directories.json",
"service_name": "RANGER",
"stack_name": "BIGTOP",
"stack_version": "3.2.0",
"theme_data": {
"Theme": {
"description": "Directories theme for RANGER service",
"name": "directories",
"configuration": {
}
}
}
}
},
{
"href": "http://localhost:28080/api/v1/stacks/BIGTOP/versions/3.2.0/services/RANGER/themes/theme_version_2.json",
"ThemeInfo": {
"default": true,
"file_name": "theme_version_2.json",
"service_name": "RANGER",
"stack_name": "BIGTOP",
"stack_version": "3.2.0",
"theme_data": {
"Theme": {
"description": "Default theme for Ranger service",
"name": "default",
"configuration": {
}
}
}
}
}
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
在这个结构中,我们可以看到每个配置文件的 placement
和 widget
等关键信息。通过分析这些字段,可以精确控制页面中各个部分的显示与功能。这一发现让我进一步追踪代码,确认
Ambari 如何通过这些 JSON 文件渲染 UI。
接下来,我深入阅读了 Ambari 的前端源码,特别是 app/mixins/main/service/themes_mapping.js
文件:
首先,我们通过 loadConfigTheme
方法加载服务的主题配置数据:
App.ThemesMappingMixin = Em.Mixin.create({
/**
* 从服务器加载指定服务的配置主题
* @param {string} serviceName 服务名称
* @returns {$.ajax} 返回一个异步请求的 promise
* @method loadConfigTheme
*/
loadConfigTheme: function (serviceName) {
const dfd = $.Deferred(); // 创建一个延迟对象,方便处理异步流程
if (App.Tab.find().mapProperty('serviceName').contains(serviceName)) {
// 如果服务已经加载过,直接resolve,避免重复请求
dfd.resolve();
} else {
App.ajax.send({
name: 'configs.theme', // 配置请求的名称
sender: this,
data: {
serviceName: serviceName, // 请求中传递的服务名称
stackVersionUrl: App.get('stackVersionURL') // 获取当前栈的版本URL
},
success: '_saveThemeToModel' // 成功回调,处理返回的数据
}).complete(dfd.resolve); // 在请求完成后,无论成功或失败都resolve
}
return dfd.promise(); // 返回 promise,用于调用链的处理
},
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# loadConfigTheme
方法解析
- 这个方法的核心功能是向服务器发送请求,获取指定服务的主题配置。
- 它首先检查主题是否已经加载过,如果加载过则跳过请求,直接
resolve
,从而提升性能。 - 如果服务的主题尚未加载,则通过
App.ajax.send
发送 AJAX 请求,向服务端获取主题配置。 - 成功获取主题配置后,调用
this._saveThemeToModel
方法,将主题数据保存到前端模型中。
成功回调 _saveThemeToModel
方法如下:
/**
* 成功回调,将获取的主题数据映射保存到模型
* @param {object} data 从服务器返回的数据
* @param {object} opt AJAX 请求选项
* @param {object} params 请求的参数
* @private
* @method saveThemeToModel
*/
_saveThemeToModel: function (data, opt, params) {
App.themesMapper.map(data, [params.serviceName]); // 使用 themesMapper 将数据映射到指定服务
}
,
2
3
4
5
6
7
8
9
10
11
12
# _saveThemeToModel
方法解析
- 该方法的作用是将从服务器返回的主题数据映射到前端模型中。
- 它使用了
App.themesMapper.map
方法,将获取到的数据与指定的serviceName
进行绑定,从而将配置的主题内容与服务的 UI 对应起来。 - 这一步完成后,页面可以根据这些主题配置来渲染服务的相关 UI。
接下来,App.themesMapper.map
方法负责将数据映射到模型中,该方法位于 app/mappers/themes_mapper.js
文件中。通过这个方法,JSON
文件中的主题数据将被解析并保存到前端应用的模型中,供 UI 渲染时使用。
App.themesMapper = App.QuickDataMapper.create({
map: function (data, serviceNames) {
serviceNames.forEach(function (serviceName) {
var serviceTheme = data.items.find(item => item.ThemeInfo.service_name === serviceName);
if (serviceTheme) {
// 将解析后的 theme_data 存入相应的服务模型中
App.Tab.find().findProperty('serviceName', serviceName).set('theme', serviceTheme.ThemeInfo.theme_data.Theme);
}
});
}
});
2
3
4
5
6
7
8
9
10
11
# themesMapper.map
方法解析
themesMapper.map
是一个快速映射工具,它遍历从服务器返回的主题配置文件,并将其中的主题数据映射到对应的服务模型上。- 通过
findProperty
方法,它找到与服务名称相匹配的服务,并将主题数据保存在该服务的theme
属性中。 - 此时,前端模型中的主题数据就准备好供页面使用了。
通过这段源码,我们清楚地了解到 Ambari 是如何通过 AJAX 请求从服务器获取主题配置,并将这些配置数据映射到前端模型中。在主题配置加载到模型之后,页面就可以根据这些配置来调整 UI 的布局和风格。