 61f21da7e6
			
		
	
	61f21da7e6
	
	
	
		
			
			1. Update datas to data 2. Update metadatas to metadata 3. Update data intro && codes in docs Change-Id: I2041b69c6d9a9e9ec61c3861ad8860af5ac5cc0b
		
			
				
	
	
	
		
			16 KiB
		
	
	
	
	
	
	
	
			
		
		
	
	简体中文 | English
用途
- 数据请求的处理
- 支持获取全部数据
- 支持分页获取数据
- 支持对数据的各种请求处理(PUT、POST、GET、PATCH、DELETE、HEAD 等)
BaseStore 代码文件
- src/stores/base.js
BaseStore 属性与函数定义介绍
- 资源数据的 Store 继承于 BaseStore 类
- 代码位置:src/stores/xxx/xxx.js,如云主机对应的 store 在src/stores/nova/instance.js
- 只需要复写部分函数即可完成数据的请求操作
- 属性与函数分为以下四种,
- 通常需要复写的属性与函数,主要包含:
- 与生成 url 相关的属性与函数
 
- 按需复写的函数与属性,主要包含:
- 列表数据的再加工
- 详情数据的再加工
- 请求参数的处理
- url 的处理
 
- 无需复写的函数与属性,主要包含:
- 清空数据
- 封装数据时对项目信息的处理
 
- 基类中的基础函数,主要包含:
- 处理分页数据的marker
 
- 处理分页数据的
- 更详细与全面的介绍见下
 
- 通常需要复写的属性与函数,主要包含:
名词说明
- 前端分页
- 一次性从后端获取所有列表数据
- 前端基于获取到的数据总量、页面内配置的当前页数、每页数量来展示数据(BaseList组件处理)
 
- 后端分页
- 以当前页号、每页数量向后端请求数据
 
- 前端排序
- 使用前端分页时,按设定的排序信息对所有数据排序
- 使用后端分页时,按设定的排序信息对当前页内的数据排序
 
- 后端排序
- 以当前页号、每页数量、当前排序信息向后端请求数据
- 不存在前端分页+后端排序这种组合方式
 
通常需要复写的属性与函数
- 
module:- 
必须复写该函数 
- 
资源对应的模块 
- 
该函数用于生成请求的 url 
- 
以云主机 src/stores/nova/instance.js为例get module() { return 'servers'; }
 
- 
- 
apiVersion- 
必须复写该函数 
- 
资源对应的 api 前缀 
- 
因所有的请求需要由服务端转发,所以,api 的前缀需要基于 profile内的信息生成
- 
以云主机 src/stores/nova/instance.js为例get apiVersion() { return novaBase(); }
 
- 
- 
responseKey
按需复写的属性与函数
- 
listDidFetch- 
列表数据二次加工使用的函数 
- 
可请求其他 API 后,整合数据 
- 
可过滤数据 
- 
请求某个指定云硬盘的快照列表时,可以基于 filters中的参数再次过滤数据- 
以云硬盘快照 src/stores/cinder/snapshot.js为例async listDidFetch(items, allProjects, filters) { if (items.length === 0) { return items; } const { id } = filters; const data = id ? items.filter((it) => it.volume_id === id) : items; return data; }
 
- 
- 
如果需要显示加密信息,需要发起额外请求后,整合数据 - 
以云硬盘类型 src/stores/cinder/volume-type.js为例async listDidFetch(items, allProjects, filters) { const { showEncryption } = filters; if (items.length === 0) { return items; } if (!showEncryption) { return items; } const promiseList = items.map((i) => request.get(`${this.getDetailUrl({ id: i.id })}/encryption`) ); const encryptionList = await Promise.all(promiseList); const result = items.map((i) => { const { id } = i; const encryption = encryptionList.find((e) => e.volume_type_id === id); return { ...i, encryption, }; }); return result; }
 
- 
 
- 
- 
detailDidFetch- 
详情数据二次加工使用的函数 
- 
可请求其他 API 后,整合数据 
- 
以云硬盘快照 src/stores/cinder/snapshot.js为例async detailDidFetch(item) { const { volume_id } = item; const volumeUrl = `${cinderBase()}/${ globals.user.project.id }/volumes/${volume_id}`; const { volume } = await request.get(volumeUrl); item.volume = volume; return item; }
 
- 
- 
listResponseKey- 
列表数据的返回 Key 
- 
默认是 ${this.responseKey}s
- 
以云硬盘快照 src/stores/cinder/snapshot.js为例get responseKey() { return 'snapshot'; } get listResponseKey() { return 'volume_snapshots'; }
 
- 
- 
getListUrl- 
请求数据使用的 url 
- 
前端分页请求列表数据(即一次性获取所有数据)时,优先使用 this.getListDetailUrl()
- 
后端分页请求列表数据时,按优先级 this.getListPageUrl()>this.getListDetailUrl()>this.getListUrl()
- 
默认值为 getListUrl = () => `${this.apiVersion}/${this.module}`;
- 
以 Heat 的堆栈的日志 src/stores/heat/event.js为例getListUrl = ({ id, name }) => `${this.apiVersion}/${this.module}/${name}/${id}/events`;
 
- 
- 
getListDetailUrl- 
请求数据使用的 url 
- 
前端分页请求列表数据(即一次性获取所有数据)时,优先使用 this.getListDetailUrl()
- 
后端分页请求列表数据时,按优先级 this.getListPageUrl()>this.getListDetailUrl()>this.getListUrl()
- 
默认值为 getListDetailUrl = () => '';
- 
以云硬盘 src/stores/cinder/volume.js为例getListDetailUrl = () => `${skylineBase()}/extension/volumes`;
 
- 
- 
getListPageUrl- 
后端分页数据使用的 url 
- 
后端分页请求列表数据时,按优先级 this.getListPageUrl()>this.getListDetailUrl()>this.getListUrl()
- 
默认值为 getListPageUrl = () => '';
- 
以云硬盘 src/stores/cinder/volume.js为例getListPageUrl = () => `${skylineBase()}/extension/volumes`;
 
- 
- 
getDetailUrl- 
详情数据对应的 url 
- 
使用 rest 风格的 API,所以,该 url 也是 put, delete, patch 对应的 url 
- 
默认值为 getDetailUrl = ({ id }) => `${this.getListUrl()}/${id}`;
- 
以堆栈 src/stores/heat/stack.js为例getDetailUrl = ({ id, name }) => `${this.getListUrl()}/${name}/${id}`;
 
- 
- 
needGetProject- 
对服务端返回的数据是否需要二次加工其中的项目信息 
- 
一般 Openstack API 返回的数据只有 project_id信息,按页面展示的需求,在管理平台需要展示项目名称
- 
默认值是 true
- 
以元数据 src/stores/glance/metadata.js为例get needGetProject() { return false; }
 
- 
- 
mapper- 
对服务端返回的列表、详情数据做二次加工 
- 
一般是为了更便捷的在资源列表、资源详情中展示数据使用 
- 
默认值为 get mapper() { return (data) => data; }
- 
以云硬盘 src/stores/cinder/volume.js为例get mapper() { return (volume) => ({ ...volume, disk_tag: isOsDisk(volume) ? 'os_disk' : 'data_disk', description: volume.description || (volume.origin_data || {}).description, }); }
 
- 
- 
mapperBeforeFetchProject- 
在处理项目信息前,对服务端返回的列表、详情数据做二次加工 
- 
一般是为了处理返回数据中的项目信息使用 
- 
默认值为 get mapperBeforeFetchProject() { return (data) => data; }
- 
以镜像 src/stores/glance/image.js为例get mapperBeforeFetchProject() { return (data, filters, isDetail) => { if (isDetail) { return { ...data, project_id: data.owner, }; } return { ...data, project_id: data.owner, project_name: data.owner_project_name || data.project_name, }; }; }
 
- 
- 
paramsFunc- 
前端分页请求(即 fetchList)时,对请求参数的更新
- 
默认是对从资源列表代码( pages/xxxx/xxx/index.jsx)使用fetchList时,参数的过滤
- 
默认值 get paramsFunc() { if (this.filterByApi) { return (params) => params; } return (params) => { const reservedKeys = [ 'all_data', 'all_projects', 'device_id', 'network_id', 'floating_network_id', 'start_at_gt', 'start_at_lt', 'binary', 'fixed_ip_address', 'device_owner', 'project_id', 'type', 'sort', 'security_group_id', 'id', 'security_group_id', 'owner_id', 'status', 'fingerprint', 'resource_types', 'floating_ip_address', 'uuid', 'loadbalancer_id', 'ikepolicy_id', 'ipsecpolicy_id', 'endpoint_id', 'peer_ep_group_id', 'local_ep_group_id', 'vpnservice_id', ]; const newParams = {}; Object.keys(params).forEach((key) => { if (reservedKeys.indexOf(key) >= 0) { newParams[key] = params[key]; } }); return newParams; }; }
- 
以云硬盘 src/stores/cinder/volume.js为例get paramsFunc() { return (params) => { const { serverId, ...rest } = params; return rest; }; }
 
- 
- 
paramsFuncPage- 
后端分页请求(即 fetchListByPage)时,对请求参数的更新
- 
默认是对从资源列表代码( pages/xxxx/xxx/index.jsx)使用fetchListByPage时,参数的过滤
- 
默认值 get paramsFuncPage() { return (params) => { const { current, ...rest } = params; return rest; }; }
- 
以云硬盘类型 src/stores/cinder/volume-type.js为例get paramsFuncPage() { return (params) => { const { current, showEncryption, ...rest } = params; return rest; }; }
 
- 
- 
fetchListByLimit- 
前端分页请求所有数据时,是否要基于 limit发起多个请求,最终实现所有数据的获取
- 
Openstack API 默认返回的是 1000 个数据,对于某些资源数据很多的情况,需要使用该配置以便获取到所有数据 
- 
默认值是 false
- 
以镜像 src/stores/glance/image.js为例get fetchListByLimit() { return true; }
 
- 
- 
markerKey- 
后端分页请求数据时,marker 的来源 
- 
因为对 Openstack 的请求是由后端转发的,所以并没有直接使用列表数据返回的 Openstack 拼接好的下一页数据应该使用的 Url,而是根据返回的数据,解析出 marker
- 
默认值是 id
- 
通常不需要复写 
- 
以密钥 src/stores/nova/keypair.js为例get markerKey() { return 'keypair.name'; }
 
- 
- 
requestListByMarker- 
后端分页时,使用 marker请求分页下的数据
- 
通常不需要复写 
- 
默认值是 async requestListByMarker(url, params, limit, marker) { const newParams = { ...params, limit, }; if (marker) { newParams.marker = marker; } return request.get(url, newParams); }
- 
以云主机组 src/stores/nova/server-group.js为例async requestListByMarker(url, params, limit, marker) { const newParams = { ...params, limit, }; if (marker) { newParams.offset = marker; } return request.get(url, newParams); }
 
- 
- 
requestListAllByLimit- 当this.fetchListByLimit=true时,前端分页使用该方法获取所有数据
- 通常不需要复写
 
- 当
- 
updateUrl- 更新列表数据请求的 url
- 不常用
 
- 
updateParamsSortPage- 
使用后端排序时,对排序参数的处理 
- 
使用后端排序时,会在资源列表代码 pages/xxx/XXX/index.jsx中自动生成相应的请求参数,store 对这些参数往往需要再次整理,否则会不符合 API 的参数要求
- 
以云硬盘 src/stores/cinder/volume.js为例updateParamsSortPage = (params, sortKey, sortOrder) => { if (sortKey && sortOrder) { params.sort_keys = sortKey; params.sort_dirs = sortOrder === 'descend' ? 'desc' : 'asc'; } };
 
- 
- 
listFilterByProject- 
列表数据是否需要基于项目信息过滤 
- 
admin权限下的部分 Openstack 资源(如neutron),会默认返回所有项目的数据,所以在控制台展示资源时,会根据该配置过滤数据
- 
默认值是 false
- 
以 VPN src/stores/neutron/vpn-service.js为例get listFilterByProject() { return true; }
 
- 
- 
fetchList- pages下的列表页通常使用- this.store.fetchList来获取前端分页数据
- 不建议复写该函数,如果需要再加工数据,建议使用listDidFetch
- 该函数会更新this.list属性中的相关数据,pages下的资源列表组件也是基于this.list进行数据展示
 
- 
fetchListByPage- pages下的列表页通常使用- this.store.fetchList来获取后端分页数据
- 不建议复写该函数,如果需要再加工数据,建议使用listDidFetch
- 该函数会更新this.list属性中的相关数据,pages下的资源列表组件也是基于this.list进行数据展示
 
- 
getCountForPage- 获取列表数据的总量
- 通常在后端分页时可复写
 
- 
getDetailParams- 
更新详情数据请求时的参数 
- 
默认值为 getDetailParams = () => undefined;
 
- 
- 
fetchDetail- pages下的详情页通常使用- this.store.fetchDetail来获取详情数据
- 通常不需要复写
- 数据再加工通常是重写mapper或detailDidFetch
 
- 
create- 创建资源
- 使用POSTapi
- 通常不需要复写
- 使用this.submitting保证在发送请求时页面处于loading状态
 
- 
edit- 更新资源
- 使用PUTapi
- 通常不需要复写
- 使用this.submitting保证在发送请求时页面处于loading状态
 
- 
patch- 更新资源
- 使用PATCHapi
- 通常不需要复写
- 使用this.submitting保证在发送请求时页面处于loading状态
 
- 
delete- 删除资源
- 使用DELETEapi
- 通常不需要复写
- 使用this.submitting保证在发送请求时页面处于loading状态
 
不需要复写的属性与函数
- submitting- 用于数据创建、数据更新时
- 依据请求的响应变更this.isSubmitting,对应的 Form,列表页等会展示 Loading 状态
 
- currentProject- 当前用户登录的项目 ID
 
- itemInCurrentProject- 数据是否属于当前用户登录的项目
 
- listDidFetchProject- 对列表数据添加项目信息
 
- requestListAll- 前端分页获取所有数据
 
- requestListByPage- 后端分页所有当前页的数据
 
- pureFetchList- 列表数据的请求函数
- 返回原始数据,不会对 API 的返回数据做加工
 
- parseMarker- 使用后端分页时,从返回数据中解析出marker,用于请求上一页、下一页数据时使用
 
- 使用后端分页时,从返回数据中解析出
- updateMarker- 更新list的markers
- list.markers是个数组,每个元素对应于- 下标+1页的- marker
 
- 更新
- getMarker- 获取指定页对应的marker
 
- 获取指定页对应的
- getListDataFromResult- 从 API 的返回值中取出列表数据
- 利用this.listResponseKey获取
 
- setSelectRowKeys- 对pages下的资源列表组件列表中数据项的选中记录
 
- 对
- clearData- 清空list数据
 
- 清空
基类中的基础函数
- 建议查看代码理解,src/stores/base.js
