From 717470044bafb53a2a408ec863b657196d76420b Mon Sep 17 00:00:00 2001 From: wxsm Date: Sat, 21 Oct 2017 14:46:18 +0800 Subject: [PATCH] [Breadcrumbs] Add component --- build/webpack.dist.conf.js | 2 +- docs/main.js | 2 +- docs/pages/components/Breadcrumbs.md | 189 ++++++++++++++++++ docs/router/routes.js | 5 + src/components/breadcrumbs/BreadcrumbItem.vue | 38 ++++ src/components/breadcrumbs/Breadcrumbs.vue | 31 +++ src/components/index.js | 41 +--- src/index.js | 2 + src/install.js | 19 ++ test/unit/index.js | 7 +- test/unit/specs/Breadcrumbs.spec.js | 82 ++++++++ 11 files changed, 378 insertions(+), 40 deletions(-) create mode 100644 docs/pages/components/Breadcrumbs.md create mode 100644 src/components/breadcrumbs/BreadcrumbItem.vue create mode 100644 src/components/breadcrumbs/Breadcrumbs.vue create mode 100644 src/index.js create mode 100644 src/install.js create mode 100644 test/unit/specs/Breadcrumbs.spec.js diff --git a/build/webpack.dist.conf.js b/build/webpack.dist.conf.js index 348b1d50b..5768a7428 100644 --- a/build/webpack.dist.conf.js +++ b/build/webpack.dist.conf.js @@ -21,7 +21,7 @@ for (let i = 0; i < rules.length; i++) { let webpackConfig = { entry: { - app: './src/components/index.js' + app: './src/index.js' }, externals: { vue: { diff --git a/docs/main.js b/docs/main.js index 7c6a00d29..80626b4b6 100644 --- a/docs/main.js +++ b/docs/main.js @@ -9,7 +9,7 @@ import VueRouter from 'vue-router' import router from './router' import PageWrapper from './components/architecture/PageWrapper.vue' import MarkdownWrapper from './components/architecture/MarkdownWrapper.vue' -import * as uiv from './../src/components/index' +import * as uiv from './../src' Vue.config.productionTip = false diff --git a/docs/pages/components/Breadcrumbs.md b/docs/pages/components/Breadcrumbs.md new file mode 100644 index 000000000..7b574eb45 --- /dev/null +++ b/docs/pages/components/Breadcrumbs.md @@ -0,0 +1,189 @@ +# Breadcrumbs + +> Indicate the current page's location within a navigational hierarchy. + +## Example + +Use `items` array to create a breadcrumbs nav. `active` state of last element is automatically set if it is undefined. + +```html + + + + +``` + + +## Breadcrumb Item + +You can also use `` in breadcrumbs directly. This is useful while full control of item text is need (e.g. HTML tags). + +Note that `active` state will not automatically set if using this mode. + +```html + + Home + Library + Data + + +``` + +## Router Link + +Parse `to` (String or Object) instead of `href` will create a `router-link` for the breadcrumb item, which you can use with [Vue-Router](https://router.vuejs.org/). + +```html + + + + +``` + + + +# API Reference + +## [Breadcrumbs.vue](https://github.com/wxsms/uiv/tree/master/src/components/breadcrumbs/Breadcrumbs.vue) + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Props
NameTypeDefaultRequiredDescription
itemsArrayBreadcrumb items to create. Props defined in each item object is the same with BreadcrumbItem.vue, except text will be replace as the breadcrumb item body.
Slots
NameDescription
defaultThe breadcrumbs body.
+
+ +## [BreadcrumbItem.vue](https://github.com/wxsms/uiv/tree/master/src/components/breadcrumbs/BreadcrumbItem.vue) + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Props
NameTypeDefaultRequiredDescription
aciveBooleanfalseSet item to active state.
hrefStringAn ordinary link will be created if this prop present.
targetString_self
toString or ObjectAn Vue-Router link will be created if this prop present.
Slots
NameDescription
defaultThe breadcrumb item body.
+
diff --git a/docs/router/routes.js b/docs/router/routes.js index cad11effb..e0890af88 100644 --- a/docs/router/routes.js +++ b/docs/router/routes.js @@ -26,6 +26,11 @@ const routes = [ meta: {type: 'component', label: 'Alert'}, component: () => import('./../pages/components/Alert.md') }, + { + path: '/breadcrumbs', + meta: {type: 'component', label: 'Breadcrumbs'}, + component: () => import('./../pages/components/Breadcrumbs.md') + }, { path: '/carousel', meta: {type: 'component', label: 'Carousel'}, diff --git a/src/components/breadcrumbs/BreadcrumbItem.vue b/src/components/breadcrumbs/BreadcrumbItem.vue new file mode 100644 index 000000000..7647e5d61 --- /dev/null +++ b/src/components/breadcrumbs/BreadcrumbItem.vue @@ -0,0 +1,38 @@ + + + diff --git a/src/components/breadcrumbs/Breadcrumbs.vue b/src/components/breadcrumbs/Breadcrumbs.vue new file mode 100644 index 000000000..0da894696 --- /dev/null +++ b/src/components/breadcrumbs/Breadcrumbs.vue @@ -0,0 +1,31 @@ + + + diff --git a/src/components/index.js b/src/components/index.js index f13638a3e..6b45d0dfc 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -15,43 +15,10 @@ import TimePicker from './timepicker/TimePicker.vue' import Typeahead from './typeahead/Typeahead.vue' import ProgressBar from './progressbar/ProgressBar.vue' import ProgressBarStack from './progressbar/ProgressBarStack.vue' -import locale from './../locale' - -const components = { - Affix, - Tooltip, - Carousel, - Slide, - Collapse, - Dropdown, - Modal, - Tab, - Tabs, - DatePicker, - Alert, - Pagination, - Popover, - TimePicker, - Typeahead, - ProgressBar, - ProgressBarStack -} - -const install = (Vue, options = {}) => { - locale.use(options.locale) - locale.i18n(options.i18n) - for (let key in components) { - Vue.component(key, components[key]) - } -} - -// auto install -if (typeof window !== 'undefined' && window.Vue) { - install(window.Vue) -} +import Breadcrumbs from './breadcrumbs/Breadcrumbs.vue' +import BreadcrumbItem from './breadcrumbs/BreadcrumbItem.vue' export { - install, Affix, Tooltip, Carousel, @@ -68,5 +35,7 @@ export { TimePicker, Typeahead, ProgressBar, - ProgressBarStack + ProgressBarStack, + Breadcrumbs, + BreadcrumbItem } diff --git a/src/index.js b/src/index.js new file mode 100644 index 000000000..46e3cb29b --- /dev/null +++ b/src/index.js @@ -0,0 +1,2 @@ +export * from './components' +export * from './install' diff --git a/src/install.js b/src/install.js new file mode 100644 index 000000000..90ed058a1 --- /dev/null +++ b/src/install.js @@ -0,0 +1,19 @@ +import * as components from './components' +import locale from './locale' + +const install = (Vue, options = {}) => { + // Setup language, en-US for default + locale.use(options.locale) + locale.i18n(options.i18n) + // Register components + for (let key in components) { + Vue.component(key, components[key]) + } +} + +// auto install +if (typeof window !== 'undefined' && window.Vue) { + install(window.Vue) +} + +export { install } diff --git a/test/unit/index.js b/test/unit/index.js index bf39ac750..d3a570513 100644 --- a/test/unit/index.js +++ b/test/unit/index.js @@ -1,9 +1,12 @@ import 'es6-promise/auto' import Vue from 'vue' -import * as uiv from '@src/components/index.js' +import * as uiv from '@src/install' Vue.config.productionTip = false - +// simulate router-link +Vue.component('router-link', { + template: '' +}) Vue.use(uiv) // Polyfill fn.bind() for PhantomJS diff --git a/test/unit/specs/Breadcrumbs.spec.js b/test/unit/specs/Breadcrumbs.spec.js new file mode 100644 index 000000000..4c30bd80a --- /dev/null +++ b/test/unit/specs/Breadcrumbs.spec.js @@ -0,0 +1,82 @@ +import Vue from 'vue' +import $ from 'jquery' +import BreadcrumbsDoc from '@docs/pages/components/Breadcrumbs.md' + +describe('Breadcrumbs', () => { + let vm + let $el + + beforeEach(() => { + let Constructor = Vue.extend(BreadcrumbsDoc) + vm = new Constructor().$mount() + $el = $(vm.$el) + }) + + afterEach(() => { + vm.$destroy() + $el.remove() + }) + + it('should be able to render with items data', () => { + let b = $el.find('.breadcrumb').get(0) + expect(b.querySelectorAll('li').length).to.equal(3) + let nav1 = b.querySelectorAll('li a')[0] + expect(nav1.getAttribute('href')).to.equal('#') + expect(nav1.getAttribute('target')).to.equal('_self') + expect(nav1.textContent).to.equal('Home') + let nav2 = b.querySelectorAll('li a')[1] + expect(nav2.getAttribute('href')).to.equal('#') + expect(nav2.getAttribute('target')).to.equal('_self') + expect(nav2.textContent).to.equal('Library') + let nav3 = b.querySelectorAll('li')[2] + expect(nav3.className).to.contain('active') + expect(nav3.querySelector('a')).not.exist + expect(nav3.textContent).to.equal('Data') + }) + + it('should be able to render with ', () => { + let b = $el.find('.breadcrumb').get(1) + expect(b.querySelectorAll('li').length).to.equal(3) + let nav1 = b.querySelectorAll('li a')[0] + expect(nav1.getAttribute('href')).to.equal('#') + expect(nav1.getAttribute('target')).to.equal('_self') + expect(nav1.querySelector('b')).to.exist + expect(nav1.querySelector('b').textContent).to.equal('Home') + let nav2 = b.querySelectorAll('li a')[1] + expect(nav2.getAttribute('href')).to.equal('#') + expect(nav2.getAttribute('target')).to.equal('_self') + expect(nav2.textContent).to.equal('Library') + let nav3 = b.querySelectorAll('li')[2] + expect(nav3.className).to.contain('active') + expect(nav3.querySelector('a')).not.exist + expect(nav3.textContent).to.equal('Data') + }) + + it('should be able to render router-link', () => { + let b = $el.find('.breadcrumb').get(2) + let nav1 = b.querySelectorAll('li a')[0] + expect(nav1.getAttribute('href')).to.equal('#router-link') // router-link mock + }) + + it('should not auto active last item if using active prop', () => { + let res = Vue.compile('') + let vm = new Vue({ + data () { + return { + items: [{text: 'test', href: '#', active: false}] + } + }, + render: res.render, + staticRenderFns: res.staticRenderFns + }).$mount() + let $el = $(vm.$el) + expect(vm.$el.querySelectorAll('li').length).to.equal(1) + let nav1 = vm.$el.querySelectorAll('li a')[0] + expect(nav1.getAttribute('href')).to.equal('#') + expect(nav1.getAttribute('target')).to.equal('_self') + expect(nav1.textContent).to.equal('test') + expect($el.find('.active').length).to.equal(0) + $el.remove() + vm.$destroy() + }) +})