Breadcrumb.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
  2. import { createVNode as _createVNode } from "vue";
  3. import { cloneVNode, defineComponent } from 'vue';
  4. import PropTypes from '../_util/vue-types';
  5. import { flattenChildren, getPropsSlot } from '../_util/props-util';
  6. import warning from '../_util/warning';
  7. import BreadcrumbItem from './BreadcrumbItem';
  8. import Menu from '../menu';
  9. import useConfigInject from '../config-provider/hooks/useConfigInject';
  10. import useStyle from './style';
  11. export const breadcrumbProps = () => ({
  12. prefixCls: String,
  13. routes: {
  14. type: Array
  15. },
  16. params: PropTypes.any,
  17. separator: PropTypes.any,
  18. itemRender: {
  19. type: Function
  20. }
  21. });
  22. function getBreadcrumbName(route, params) {
  23. if (!route.breadcrumbName) {
  24. return null;
  25. }
  26. const paramsKeys = Object.keys(params).join('|');
  27. const name = route.breadcrumbName.replace(new RegExp(`:(${paramsKeys})`, 'g'), (replacement, key) => params[key] || replacement);
  28. return name;
  29. }
  30. function defaultItemRender(opt) {
  31. const {
  32. route,
  33. params,
  34. routes,
  35. paths
  36. } = opt;
  37. const isLastItem = routes.indexOf(route) === routes.length - 1;
  38. const name = getBreadcrumbName(route, params);
  39. return isLastItem ? _createVNode("span", null, [name]) : _createVNode("a", {
  40. "href": `#/${paths.join('/')}`
  41. }, [name]);
  42. }
  43. export default defineComponent({
  44. compatConfig: {
  45. MODE: 3
  46. },
  47. name: 'ABreadcrumb',
  48. inheritAttrs: false,
  49. props: breadcrumbProps(),
  50. slots: Object,
  51. setup(props, _ref) {
  52. let {
  53. slots,
  54. attrs
  55. } = _ref;
  56. const {
  57. prefixCls,
  58. direction
  59. } = useConfigInject('breadcrumb', props);
  60. const [wrapSSR, hashId] = useStyle(prefixCls);
  61. const getPath = (path, params) => {
  62. path = (path || '').replace(/^\//, '');
  63. Object.keys(params).forEach(key => {
  64. path = path.replace(`:${key}`, params[key]);
  65. });
  66. return path;
  67. };
  68. const addChildPath = (paths, childPath, params) => {
  69. const originalPaths = [...paths];
  70. const path = getPath(childPath || '', params);
  71. if (path) {
  72. originalPaths.push(path);
  73. }
  74. return originalPaths;
  75. };
  76. const genForRoutes = _ref2 => {
  77. let {
  78. routes = [],
  79. params = {},
  80. separator,
  81. itemRender = defaultItemRender
  82. } = _ref2;
  83. const paths = [];
  84. return routes.map(route => {
  85. const path = getPath(route.path, params);
  86. if (path) {
  87. paths.push(path);
  88. }
  89. const tempPaths = [...paths];
  90. // generated overlay by route.children
  91. let overlay = null;
  92. if (route.children && route.children.length) {
  93. overlay = _createVNode(Menu, {
  94. "items": route.children.map(child => ({
  95. key: child.path || child.breadcrumbName,
  96. label: itemRender({
  97. route: child,
  98. params,
  99. routes,
  100. paths: addChildPath(tempPaths, child.path, params)
  101. })
  102. }))
  103. }, null);
  104. }
  105. const itemProps = {
  106. separator
  107. };
  108. if (overlay) {
  109. itemProps.overlay = overlay;
  110. }
  111. return _createVNode(BreadcrumbItem, _objectSpread(_objectSpread({}, itemProps), {}, {
  112. "key": path || route.breadcrumbName
  113. }), {
  114. default: () => [itemRender({
  115. route,
  116. params,
  117. routes,
  118. paths: tempPaths
  119. })]
  120. });
  121. });
  122. };
  123. return () => {
  124. var _a;
  125. let crumbs;
  126. const {
  127. routes,
  128. params = {}
  129. } = props;
  130. const children = flattenChildren(getPropsSlot(slots, props));
  131. const separator = (_a = getPropsSlot(slots, props, 'separator')) !== null && _a !== void 0 ? _a : '/';
  132. const itemRender = props.itemRender || slots.itemRender || defaultItemRender;
  133. if (routes && routes.length > 0) {
  134. // generated by route
  135. crumbs = genForRoutes({
  136. routes,
  137. params,
  138. separator,
  139. itemRender
  140. });
  141. } else if (children.length) {
  142. crumbs = children.map((element, index) => {
  143. warning(typeof element.type === 'object' && (element.type.__ANT_BREADCRUMB_ITEM || element.type.__ANT_BREADCRUMB_SEPARATOR), 'Breadcrumb', "Only accepts Breadcrumb.Item and Breadcrumb.Separator as it's children");
  144. return cloneVNode(element, {
  145. separator,
  146. key: index
  147. });
  148. });
  149. }
  150. const breadcrumbClassName = {
  151. [prefixCls.value]: true,
  152. [`${prefixCls.value}-rtl`]: direction.value === 'rtl',
  153. [`${attrs.class}`]: !!attrs.class,
  154. [hashId.value]: true
  155. };
  156. return wrapSSR(_createVNode("nav", _objectSpread(_objectSpread({}, attrs), {}, {
  157. "class": breadcrumbClassName
  158. }), [_createVNode("ol", null, [crumbs])]));
  159. };
  160. }
  161. });