OHIF记录(十二)——viewer页面的浏览器url路径生成
在点开一个患者的影像后,url地址会根据患者的studyInstanceUID而改变,格式为/viewer+studyInstanceUIDS
,像这样:
如果想要了解这个url生成的原理,那么首先就需要找到点击后的onClick
函数,要分析点击后发生了什么。
在viewers/platform/ui/src/components/studyList/StudyList.js
文件中的182行调用TableRow
组件的时候,onClick
属性定义了一个匿名函数,函数有一个输入参数。
调用TableRow源码:
<TableRow
key={`${study.StudyInstanceUID}-${index}`}
onClick={StudyInstanceUID => handleSelectItem(StudyInstanceUID)}
AccessionNumber={study.AccessionNumber || ''}
modalities={study.modalities}
PatientID={study.PatientID || ''}
PatientName={study.PatientName || ''}
StudyDate={study.StudyDate}
StudyDescription={study.StudyDescription || ''}
StudyInstanceUID={study.StudyInstanceUID}
displaySize={displaySize}
/>
TableRow参数结构赋值部分代码:
const {
AccessionNumber,
isHighlighted,
modalities,
PatientID,
PatientName,
StudyDate,
StudyDescription,
StudyInstanceUID,
onClick: handleClick,
displaySize,
} = props;
进入TableRow组件里,第240行(onClick: handleClick
),用了解构别名赋值的方法,也就是说handleClick
是一个函数名,在第248行,266行,327行都调用了这个函数,函数传入的参数是StudyInstanceUID
,结合239行和189行(StudyInstanceUID={study.StudyInstanceUID}
)可以知道,传入参数的值就是患者的StudyInstanceUID。
现在已经知道在点击后传入的参数是患者的StudyInstanceUID,如果想要知道StudyInstanceUID在函数里的工作原理,就需要找到上级组件,在TableRow
组件里onClick
仅调用且返回了一个函数handleSelectItem
,在第37行(onSelectItem: handleSelectItem
),StudyList组件的参数部分用了解构别名的方法定义了handleSelectItem
函数,因此需要找到StudyList
的父组件,并找到调用StudyList
组件时候传递的onSelectItem
参数。
在Viewers/platform/viewer/src/studylist/StudyListRoute.js
文件中249-267行调用StudyList
组件,onSelectItem
属性是一个匿名函数,输出到viewerPath
变量,匿名函数调用了RoutesUtil
模块里的parseViewerPath
方法,传入了三个参数,appConfig,server,studyInstanceUID
,其中appConfig
和server
与OHIF的配置有关。
调用StudyList组件:
<StudyList
isLoading={searchStatus.isSearchingForStudies}
hasError={searchStatus.error === true}
// Rows
studies={studies}
onSelectItem={studyInstanceUID => {
const viewerPath = RoutesUtil.parseViewerPath(appConfig, server, {
studyInstanceUIDs: studyInstanceUID,
});
history.push(viewerPath);
}}
// Table Header
sort={sort}
onSort={handleSort}
filterValues={filterValues}
onFilterChange={handleFilterChange}
studyListDateFilterNumDays={appConfig.studyListDateFilterNumDays}
displaySize={displaySize}
/>
parseViewerPath
函数的定义在platform/viewer/src/routes/routesUtil.js
文件中,源码:
const parseViewerPath = (appConfig = {}, server = {}, params) => {
let viewerPath = ROUTES_DEF.default.viewer.path;
// viewerPath = '/viewer:studyInstanceUIDs'
if (appConfig.enableGoogleCloudAdapter) {
// appConfig.enableGoogleCloudAdapter 的值是 undefined,所以if里的代码不执行
viewerPath = ROUTES_DEF.gcloud.viewer.path;
}
return parsePath(viewerPath, server, params);
};
其中params
是studyInstanceUID,viewerPath
的值是'/viewer:studyInstanceUIDs'
ParsePath函数源码:
const parsePath = (path, server, params) => {
let _path = path;
//_path的值是,这个文件中ROUTES_DEF.default.viewer.path的值
const _paramsCopy = Object.assign({}, server, params);
for (let key in _paramsCopy) {
_path = UrlUtil.paramString.replaceParam(_path, key, _paramsCopy[key]);
}
return _path;
};
_paramsCopy
的作用是将server
和params
两个对象的内容合并,在for循环里,key
变量会遍历_paramsCopy
对象的所有属性,_paramsCopy[key]
是属性对应的属性值。循环里调用了UrlUtil.paramString
模块的replaceParam
函数。函数在platform/core/src/utils/urlUtil.js
文件中。
函数源码:
const replaceParam = (path = '', paramKey, paramValue) => {
/*
这个函数的作用是把
platfrom/viewer/src/routes/routesUtil.js文件中ROUTES_DEF.default.viewer.path的固定的值
替换为不同的studyInstanceUIDs的url
源码具体案例就是将:
/viewer:studyInstanceUIDs' 替换为 /viewer1.2.840.113704.1.111.7512.1553386080.1
viewer后边的数字只是举个例子。
*/
const paramPattern = `${PARAM_PATTERN_IDENTIFIER}${paramKey}`;
//这段字符串是一个冒号加上platfrom/viewer/src/routes/routesUtil.js中parsePath函数里边的_paramsCopy对象的key值
//例如: :active, :enableStudyLazyLoad, :name, :studyInstanceUIDs
if (paramValue) {
//path的值是platfrom/viewer/src/routes/routesUtil.js文件中ROUTES_DEF.default.viewer.path的值
//path: '/viewer:studyInstanceUIDs'
return path.replace(paramPattern, paramValue);
}
return path;
};
path
的值是'/viewer:studyInstanceUIDs'
只有当第二个参数paramValue
(即传入的key参数)为studyInstanceUIDs
时,replace
函数才生效,会将:studyInstanceUIDs
替换为具体患者的studyInstanceUID值并返回。返回的这个值就是浏览器url上的路径。
返回值最终会传入StudyList组件里history.push函数中。