diff --git a/build/config.js b/build/config.js
index 954463dbe..9648f68e5 100644
--- a/build/config.js
+++ b/build/config.js
@@ -1,5 +1,5 @@
module.exports = {
dev: {
- componentName: 'button', // dev components
+ componentName: 'breadcrumb', // dev components
},
};
diff --git a/components/breadcrumb/Breadcrumb.jsx b/components/breadcrumb/Breadcrumb.jsx
index 82af7120b..6b17d93f3 100644
--- a/components/breadcrumb/Breadcrumb.jsx
+++ b/components/breadcrumb/Breadcrumb.jsx
@@ -4,10 +4,12 @@ import { filterEmpty, getComponentFromProp, getSlotOptions } from '../_util/prop
import warning from '../_util/warning';
import { ConfigConsumerProps } from '../config-provider';
import BreadcrumbItem from './BreadcrumbItem';
+import Menu from '../menu';
const Route = PropTypes.shape({
path: PropTypes.string,
breadcrumbName: PropTypes.string,
+ children: PropTypes.array,
}).loose;
const BreadcrumbProps = {
@@ -42,6 +44,62 @@ export default {
const name = getBreadcrumbName(route, params);
return isLastItem ? {name} : {name};
},
+ getPath(path, params) {
+ path = (path || '').replace(/^\//, '');
+ Object.keys(params).forEach(key => {
+ path = path.replace(`:${key}`, params[key]);
+ });
+ return path;
+ },
+
+ addChildPath(paths, childPath, params) {
+ const originalPaths = [...paths];
+ const path = this.getPath(childPath, params);
+ if (path) {
+ originalPaths.push(path);
+ }
+ return originalPaths;
+ },
+
+ genForRoutes({ routes = [], params = {}, separator, itemRender = defaultItemRender }) {
+ const paths = [];
+ return routes.map(route => {
+ const path = this.getPath(route.path, params);
+
+ if (path) {
+ paths.push(path);
+ }
+ // generated overlay by route.children
+ let overlay = null;
+ if (route.children && route.children.length) {
+ overlay = (
+
+ );
+ }
+
+ return (
+
+ {itemRender({ route, params, routes, paths, h: this.$createElement })}
+
+ );
+ });
+ },
},
render() {
let crumbs;
@@ -51,29 +109,22 @@ export default {
const children = filterEmpty($slots.default);
const separator = getComponentFromProp(this, 'separator');
+ const itemRender = this.itemRender || $scopedSlots.itemRender || this.defaultItemRender;
if (routes && routes.length > 0) {
- const paths = [];
- const itemRender = this.itemRender || $scopedSlots.itemRender || this.defaultItemRender;
- crumbs = routes.map(route => {
- route.path = route.path || '';
- let path = route.path.replace(/^\//, '');
- Object.keys(params).forEach(key => {
- path = path.replace(`:${key}`, params[key]);
- });
- if (path) {
- paths.push(path);
- }
- return (
-
- {itemRender({ route, params, routes, paths, h })}
-
- );
+ // generated by route
+ crumbs = this.genForRoutes({
+ routes,
+ params,
+ separator,
+ itemRender,
});
} else if (children.length) {
crumbs = children.map((element, index) => {
warning(
- getSlotOptions(element).__ANT_BREADCRUMB_ITEM,
- "Breadcrumb only accepts Breadcrumb.Item as it's children",
+ getSlotOptions(element).__ANT_BREADCRUMB_ITEM ||
+ getSlotOptions(element).__ANT_BREADCRUMB_SEPARATOR,
+ 'Breadcrumb',
+ "Only accepts Breadcrumb.Item and Breadcrumb.Separator as it's children",
);
return cloneElement(element, {
props: { separator },
diff --git a/components/breadcrumb/BreadcrumbItem.jsx b/components/breadcrumb/BreadcrumbItem.jsx
index f90cb023e..bfebfb63c 100644
--- a/components/breadcrumb/BreadcrumbItem.jsx
+++ b/components/breadcrumb/BreadcrumbItem.jsx
@@ -1,6 +1,8 @@
import PropTypes from '../_util/vue-types';
import { hasProp, getComponentFromProp } from '../_util/props-util';
import { ConfigConsumerProps } from '../config-provider';
+import DropDown from '../dropdown/dropdown';
+import Icon from '../icon';
export default {
name: 'ABreadcrumbItem',
@@ -8,16 +10,37 @@ export default {
props: {
prefixCls: PropTypes.string,
href: PropTypes.string,
- separator: PropTypes.any,
+ separator: PropTypes.any.def('/'),
+ overlay: PropTypes.any,
},
inject: {
configProvider: { default: () => ConfigConsumerProps },
},
+ methods: {
+ /**
+ * if overlay is have
+ * Wrap a DropDown
+ */
+ renderBreadcrumbNode(breadcrumbItem, prefixCls) {
+ const overlay = getComponentFromProp(this, 'overlay');
+ if (overlay) {
+ return (
+
+
+ {breadcrumbItem}
+
+
+
+ );
+ }
+ return breadcrumbItem;
+ },
+ },
render() {
const { prefixCls: customizePrefixCls, $slots } = this;
const getPrefixCls = this.configProvider.getPrefixCls;
const prefixCls = getPrefixCls('breadcrumb', customizePrefixCls);
-
+ const separator = getComponentFromProp(this, 'separator');
const children = $slots.default;
let link;
if (hasProp(this, 'href')) {
@@ -25,13 +48,15 @@ export default {
} else {
link = {children};
}
+ // wrap to dropDown
+ link = this.renderBreadcrumbNode(link, prefixCls);
if (children) {
return (
{link}
-
- {getComponentFromProp(this, 'separator') || '/'}
-
+ {separator && separator !== '' && (
+ {separator}
+ )}
);
}
diff --git a/components/breadcrumb/BreadcrumbSeparator.jsx b/components/breadcrumb/BreadcrumbSeparator.jsx
new file mode 100644
index 000000000..09f0b2c6f
--- /dev/null
+++ b/components/breadcrumb/BreadcrumbSeparator.jsx
@@ -0,0 +1,21 @@
+import { ConfigConsumerProps } from '../config-provider';
+import PropTypes from '../_util/vue-types';
+
+export default {
+ name: 'ABreadcrumbSeparator',
+ __ANT_BREADCRUMB_SEPARATOR: true,
+ props: {
+ prefixCls: PropTypes.string,
+ },
+ inject: {
+ configProvider: { default: () => ConfigConsumerProps },
+ },
+ render() {
+ const { prefixCls: customizePrefixCls, $slots } = this;
+ const getPrefixCls = this.configProvider.getPrefixCls;
+ const prefixCls = getPrefixCls('breadcrumb', customizePrefixCls);
+
+ const children = $slots.default;
+ return {children || '/'};
+ },
+};
diff --git a/components/breadcrumb/__tests__/Breadcrumb.test.js b/components/breadcrumb/__tests__/Breadcrumb.test.js
index e247b57aa..fc6c07515 100644
--- a/components/breadcrumb/__tests__/Breadcrumb.test.js
+++ b/components/breadcrumb/__tests__/Breadcrumb.test.js
@@ -13,7 +13,7 @@ describe('Breadcrumb', () => {
});
// // https://github.com/airbnb/enzyme/issues/875
- it('warns on non-Breadcrumb.Item children', () => {
+ it('warns on non-Breadcrumb.Item and non-Breadcrumb.Separator children', () => {
mount({
render() {
return (
@@ -25,7 +25,7 @@ describe('Breadcrumb', () => {
});
expect(errorSpy.mock.calls).toHaveLength(1);
expect(errorSpy.mock.calls[0][0]).toMatch(
- "Breadcrumb only accepts Breadcrumb.Item as it's children",
+ "Warning: [antdv: Breadcrumb] Only accepts Breadcrumb.Item and Breadcrumb.Separator as it's children",
);
});
@@ -61,4 +61,50 @@ describe('Breadcrumb', () => {
});
expect(wrapper.html()).toMatchSnapshot();
});
+ it('should render a menu', () => {
+ const routes = [
+ {
+ path: 'index',
+ breadcrumbName: 'home',
+ },
+ {
+ path: 'first',
+ breadcrumbName: 'first',
+ children: [
+ {
+ path: '/general',
+ breadcrumbName: 'General',
+ },
+ {
+ path: '/layout',
+ breadcrumbName: 'Layout',
+ },
+ {
+ path: '/navigation',
+ breadcrumbName: 'Navigation',
+ },
+ ],
+ },
+ {
+ path: 'second',
+ breadcrumbName: 'second',
+ },
+ ];
+ const wrapper = mount(Breadcrumb, { propsData: { routes } });
+ expect(wrapper.html()).toMatchSnapshot();
+ });
+
+ it('should support custom attribute', () => {
+ const wrapper = mount({
+ render() {
+ return (
+
+ xxx
+ yyy
+
+ );
+ },
+ });
+ expect(wrapper.html()).toMatchSnapshot();
+ });
});
diff --git a/components/breadcrumb/__tests__/__snapshots__/Breadcrumb.test.js.snap b/components/breadcrumb/__tests__/__snapshots__/Breadcrumb.test.js.snap
index faa3fc8b8..bf76d0d88 100644
--- a/components/breadcrumb/__tests__/__snapshots__/Breadcrumb.test.js.snap
+++ b/components/breadcrumb/__tests__/__snapshots__/Breadcrumb.test.js.snap
@@ -6,3 +6,11 @@ exports[`Breadcrumb should not display Breadcrumb Item when its children is fals
xxx/yyy/
`;
+
+exports[`Breadcrumb should render a menu 1`] = `
+
+`;
+
+exports[`Breadcrumb should support custom attribute 1`] = `xxx/yyy/
`;
diff --git a/components/breadcrumb/__tests__/__snapshots__/demo.test.js.snap b/components/breadcrumb/__tests__/__snapshots__/demo.test.js.snap
index 60427dd32..79edce515 100644
--- a/components/breadcrumb/__tests__/__snapshots__/demo.test.js.snap
+++ b/components/breadcrumb/__tests__/__snapshots__/demo.test.js.snap
@@ -2,6 +2,12 @@
exports[`renders ./components/breadcrumb/demo/basic.md correctly 1`] = ``;
+exports[`renders ./components/breadcrumb/demo/overlay.md correctly 1`] = `
+
+`;
+
exports[`renders ./components/breadcrumb/demo/router.md correctly 1`] = ``;
exports[`renders ./components/breadcrumb/demo/separator.md correctly 1`] = `
@@ -11,6 +17,8 @@ exports[`renders ./components/breadcrumb/demo/separator.md correctly 1`] = `
`;
+exports[`renders ./components/breadcrumb/demo/separator-indepent.md correctly 1`] = ``;
+
exports[`renders ./components/breadcrumb/demo/withIcon.md correctly 1`] = `
/ Application List/
Application
diff --git a/components/breadcrumb/demo/index.vue b/components/breadcrumb/demo/index.vue
index 1ec3cf19d..ab4d25c02 100644
--- a/components/breadcrumb/demo/index.vue
+++ b/components/breadcrumb/demo/index.vue
@@ -3,6 +3,8 @@ import Basic from './basic.md';
import WithIcon from './withIcon.md';
import Separator from './separator.md';
import Router from './router';
+import Overlay from './Overlay';
+import SeparatorIndepent from './separator-indepent';
import US from './../index.en-US.md';
import CN from './../index.zh-CN.md';
@@ -41,6 +43,8 @@ export default {
+
+
diff --git a/components/breadcrumb/demo/overlay.md b/components/breadcrumb/demo/overlay.md
new file mode 100644
index 000000000..323efd389
--- /dev/null
+++ b/components/breadcrumb/demo/overlay.md
@@ -0,0 +1,39 @@
+
+ #### 带下拉菜单的面包屑
+ 面包屑支持下拉菜单。
+
+
+
+ #### Bread crumbs with drop down menu
+ Breadcrumbs support drop down menu.
+
+
+```tpl
+
+
+ Ant Design Vue
+ Component
+
+ General
+
+
+
+ General
+
+
+
+
+ Layout
+
+
+
+
+ Navigation
+
+
+
+
+ Button
+
+
+```
diff --git a/components/breadcrumb/demo/router.md b/components/breadcrumb/demo/router.md
index 82a1ebe1b..fd33dad1d 100644
--- a/components/breadcrumb/demo/router.md
+++ b/components/breadcrumb/demo/router.md
@@ -30,19 +30,33 @@ Used together with `vue-router`
data() {
const { lang } = this.$route.params;
return {
- basePath: `/${lang}/components/breadcrumb`,
+ basePath: '/components/breadcrumb',
routes: [
{
path: 'index',
- breadcrumbName: '首页',
+ breadcrumbName: 'home',
},
{
path: 'first',
- breadcrumbName: '一级面包屑',
+ breadcrumbName: 'first',
+ children: [
+ {
+ path: '/general',
+ breadcrumbName: 'General',
+ },
+ {
+ path: '/layout',
+ breadcrumbName: 'Layout',
+ },
+ {
+ path: '/navigation',
+ breadcrumbName: 'Navigation',
+ },
+ ],
},
{
path: 'second',
- breadcrumbName: '当前页面',
+ breadcrumbName: 'second',
},
],
};
diff --git a/components/breadcrumb/demo/separator-indepent.md b/components/breadcrumb/demo/separator-indepent.md
new file mode 100644
index 000000000..afe6f758f
--- /dev/null
+++ b/components/breadcrumb/demo/separator-indepent.md
@@ -0,0 +1,23 @@
+
+ #### 分隔符
+ 使用 `Breadcrumb.Separator` 可以自定义分隔符。
+
+
+
+ #### Configuring the Separator
+ The separator can be customized by setting the separator property: `Breadcrumb.Separator`
+
+
+```tpl
+
+
+ Location
+ :
+ Application Center
+
+ Application List
+
+ An Application
+
+
+```
diff --git a/components/breadcrumb/index.en-US.md b/components/breadcrumb/index.en-US.md
index 62953638f..89a6261f9 100644
--- a/components/breadcrumb/index.en-US.md
+++ b/components/breadcrumb/index.en-US.md
@@ -1,11 +1,24 @@
## API
-| Property | Description | Type | Optional | Default |
-| --- | --- | --- | --- | --- |
-| itemRender | Custom item renderer, slot="itemRender" and slot-scope="{route, params, routes, paths}" | ({route, params, routes, paths, h}) => vNode | | - |
-| params | Routing parameters | object | | - |
-| routes | The routing stack information of router | object\[] | | - |
-| separator | Custom separator | string\|slot | | `/` |
+| Property | Description | Type | Optional | Default | Version |
+| --- | --- | --- | --- | --- | --- |
+| itemRender | Custom item renderer, slot="itemRender" and slot-scope="{route, params, routes, paths}" | ({route, params, routes, paths, h}) => vNode | | - | |
+| params | Routing parameters | object | | - | |
+| routes | The routing stack information of router | [routes\[\]](#routes) | | - | |
+| separator | Custom separator | string\|slot | | `/` | |
+
+### routes
+
+```ts
+interface Route {
+ path: string;
+ breadcrumbName: string;
+ children: Array<{
+ path: string;
+ breadcrumbName: string;
+ }>;
+}
+```
### Use with browserHistory
@@ -31,15 +44,29 @@ The link of Breadcrumb item targets `#` by default, you can use `itemRender` to
routes: [
{
path: 'index',
- breadcrumbName: '首页',
+ breadcrumbName: 'home',
},
{
path: 'first',
- breadcrumbName: '一级面包屑',
+ breadcrumbName: 'first',
+ children: [
+ {
+ path: '/general',
+ breadcrumbName: 'General',
+ },
+ {
+ path: '/layout',
+ breadcrumbName: 'Layout',
+ },
+ {
+ path: '/navigation',
+ breadcrumbName: 'Navigation',
+ },
+ ],
},
{
path: 'second',
- breadcrumbName: '当前页面',
+ breadcrumbName: 'second',
},
],
};
diff --git a/components/breadcrumb/index.js b/components/breadcrumb/index.js
index 4387b6959..f740b2def 100644
--- a/components/breadcrumb/index.js
+++ b/components/breadcrumb/index.js
@@ -1,14 +1,17 @@
import Breadcrumb from './Breadcrumb';
import BreadcrumbItem from './BreadcrumbItem';
+import BreadcrumbSeparator from './BreadcrumbSeparator';
import Base from '../base';
Breadcrumb.Item = BreadcrumbItem;
+Breadcrumb.Separator = BreadcrumbSeparator;
/* istanbul ignore next */
Breadcrumb.install = function(Vue) {
Vue.use(Base);
Vue.component(Breadcrumb.name, Breadcrumb);
Vue.component(BreadcrumbItem.name, BreadcrumbItem);
+ Vue.component(BreadcrumbSeparator.name, BreadcrumbSeparator);
};
export default Breadcrumb;
diff --git a/components/breadcrumb/index.zh-CN.md b/components/breadcrumb/index.zh-CN.md
index 09c7c7cd2..ce15c621d 100644
--- a/components/breadcrumb/index.zh-CN.md
+++ b/components/breadcrumb/index.zh-CN.md
@@ -4,9 +4,43 @@
| --- | --- | --- | --- | --- |
| itemRender | 自定义链接函数,和 vue-router 配置使用, 也可使用 slot="itemRender" 和 slot-scope="props" | ({route, params, routes, paths, h}) => vNode | | - |
| params | 路由的参数 | object | | - |
-| routes | router 的路由栈信息 | object\[] | | - |
+| routes | router 的路由栈信息 | [routes\[\]](#routes) | | - |
| separator | 分隔符自定义 | string\|slot | | '/' |
+### Breadcrumb.Item
+
+| 参数 | 参数 | 类型 | 默认值 | 版本 |
+| ------- | -------------- | -------------------------------------- | ------ | ----- |
+| href | 链接的目的地 | string | - | 1.5.0 |
+| overlay | 下拉菜单的内容 | [Menu](/components/menu) \| () => Menu | - | 1.5.0 |
+
+#### 事件
+
+| 事件名称 | 说明 | 回调参数 | 版本 |
+| -------- | -------- | -------------------- | ---- |
+| click | 单击事件 | (e:MouseEvent)=>void | - | 1.5.0 |
+
+### Breadcrumb.Separator `3.21.0`
+
+| 参数 | 参数 | 类型 | 默认值 | 版本 |
+| ---- | ---- | ---- | ------ | ---- |
+
+
+> 注意:在使用 `Breadcrumb.Separator` 时,其父组件的分隔符必须设置为 `separator=""`,否则会出现父组件默认的分隔符。
+
+### routes
+
+```ts
+interface Route {
+ path: string;
+ breadcrumbName: string;
+ children: Array<{
+ path: string;
+ breadcrumbName: string;
+ }>;
+}
+```
+
### 和 browserHistory 配合
和 vue-router 一起使用时,默认生成的 url 路径是带有 `#` 的,如果和 browserHistory 一起使用的话,你可以使用 `itemRender` 属性定义面包屑链接。
@@ -31,15 +65,29 @@
routes: [
{
path: 'index',
- breadcrumbName: '首页',
+ breadcrumbName: 'home',
},
{
path: 'first',
- breadcrumbName: '一级面包屑',
+ breadcrumbName: 'first',
+ children: [
+ {
+ path: '/general',
+ breadcrumbName: 'General',
+ },
+ {
+ path: '/layout',
+ breadcrumbName: 'Layout',
+ },
+ {
+ path: '/navigation',
+ breadcrumbName: 'Navigation',
+ },
+ ],
},
{
path: 'second',
- breadcrumbName: '当前页面',
+ breadcrumbName: 'second',
},
],
};
diff --git a/types/breadcrumb/breadcrumb-item.d.ts b/types/breadcrumb/breadcrumb-item.d.ts
index ff01d8f20..8e380b7c1 100644
--- a/types/breadcrumb/breadcrumb-item.d.ts
+++ b/types/breadcrumb/breadcrumb-item.d.ts
@@ -11,4 +11,5 @@ export declare class BreadcrumbItem extends AntdComponent {
* @type string
*/
href?: String;
+ overlay?: any;
}
diff --git a/types/breadcrumb/breadcrumb-separator.ts b/types/breadcrumb/breadcrumb-separator.ts
new file mode 100644
index 000000000..d209f407e
--- /dev/null
+++ b/types/breadcrumb/breadcrumb-separator.ts
@@ -0,0 +1,7 @@
+// Project: https://github.com/vueComponent/ant-design-vue
+// Definitions by: akki-jat
+// Definitions: https://github.com/vueComponent/ant-design-vue/types
+
+import { AntdComponent } from '../component';
+
+export declare class BreadcrumbSeparator extends AntdComponent {}
diff --git a/types/breadcrumb/breadcrumb.d.ts b/types/breadcrumb/breadcrumb.d.ts
index cb5718cac..ca2aefc92 100644
--- a/types/breadcrumb/breadcrumb.d.ts
+++ b/types/breadcrumb/breadcrumb.d.ts
@@ -5,6 +5,7 @@
import { AntdComponent } from '../component';
import { VNode } from 'vue';
import { BreadcrumbItem } from './breadcrumb-item';
+import { BreadcrumbSeparator } from './breadcrumb-separator';
export interface Route {
path?: String;
@@ -13,6 +14,7 @@ export interface Route {
export declare class Breadcrumb extends AntdComponent {
static Item: typeof BreadcrumbItem;
+ static Separator: typeof BreadcrumbSeparator;
/**
* The routing stack information of router
* @type Route[]