diff --git a/examples/routers/form.vue b/examples/routers/form.vue index d494cf3e..b4b3a82e 100644 --- a/examples/routers/form.vue +++ b/examples/routers/form.vue @@ -2,12 +2,7 @@
- - - - - - + 提交 @@ -21,12 +16,15 @@ data () { return { formValidate: { - interest: ['吃饭', '跑步'] + interest: '' }, ruleValidate: { interest: [ - { required: true, type: 'array', min: 1, message: '至少选择一个爱好', trigger: 'change' }, - { type: 'array', max: 2, message: '最多选择两个爱好', trigger: 'change' } + { + required: true, + type: 'number', + trigger: 'change' + } ] } } diff --git a/examples/routers/menu.vue b/examples/routers/menu.vue index 3d2f8251..8190a9e6 100644 --- a/examples/routers/menu.vue +++ b/examples/routers/menu.vue @@ -1,44 +1,48 @@ @@ -46,149 +50,8 @@ export default { data () { return { - theme1: 'light' - } - }, - methods: { - s (s) { - console.log(s) + theme2: 'light' } } } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/components/base/collapse-transition.js b/src/components/base/collapse-transition.js new file mode 100644 index 00000000..4c3c43dc --- /dev/null +++ b/src/components/base/collapse-transition.js @@ -0,0 +1,79 @@ +// Thanks to https://github.com/ElemeFE/element/blob/dev/src/transitions/collapse-transition.js + +import { addClass, removeClass } from '../../utils/assist'; + +const Transition = { + beforeEnter(el) { + addClass(el, 'collapse-transition'); + if (!el.dataset) el.dataset = {}; + + el.dataset.oldPaddingTop = el.style.paddingTop; + el.dataset.oldPaddingBottom = el.style.paddingBottom; + + el.style.height = '0'; + el.style.paddingTop = 0; + el.style.paddingBottom = 0; + }, + + enter(el) { + el.dataset.oldOverflow = el.style.overflow; + if (el.scrollHeight !== 0) { + el.style.height = el.scrollHeight + 'px'; + el.style.paddingTop = el.dataset.oldPaddingTop; + el.style.paddingBottom = el.dataset.oldPaddingBottom; + } else { + el.style.height = ''; + el.style.paddingTop = el.dataset.oldPaddingTop; + el.style.paddingBottom = el.dataset.oldPaddingBottom; + } + + el.style.overflow = 'hidden'; + }, + + afterEnter(el) { + // for safari: remove class then reset height is necessary + removeClass(el, 'collapse-transition'); + el.style.height = ''; + el.style.overflow = el.dataset.oldOverflow; + }, + + beforeLeave(el) { + if (!el.dataset) el.dataset = {}; + el.dataset.oldPaddingTop = el.style.paddingTop; + el.dataset.oldPaddingBottom = el.style.paddingBottom; + el.dataset.oldOverflow = el.style.overflow; + + el.style.height = el.scrollHeight + 'px'; + el.style.overflow = 'hidden'; + }, + + leave(el) { + if (el.scrollHeight !== 0) { + // for safari: add class after set height, or it will jump to zero height suddenly, weired + addClass(el, 'collapse-transition'); + el.style.height = 0; + el.style.paddingTop = 0; + el.style.paddingBottom = 0; + } + }, + + afterLeave(el) { + removeClass(el, 'collapse-transition'); + el.style.height = ''; + el.style.overflow = el.dataset.oldOverflow; + el.style.paddingTop = el.dataset.oldPaddingTop; + el.style.paddingBottom = el.dataset.oldPaddingBottom; + } +}; + +export default { + name: 'CollapseTransition', + functional: true, + render(h, { children }) { + const data = { + on: Transition + }; + + return h('transition', data, children); + } +}; diff --git a/src/components/menu/submenu.vue b/src/components/menu/submenu.vue index b0cba7db..1fcdc55b 100644 --- a/src/components/menu/submenu.vue +++ b/src/components/menu/submenu.vue @@ -4,7 +4,9 @@
- + + + import Drop from '../select/dropdown.vue'; import Icon from '../icon/icon.vue'; + import CollapseTransition from '../base/collapse-transition'; import { getStyle, findComponentUpward } from '../../utils/assist'; import Emitter from '../../mixins/emitter'; @@ -25,7 +28,7 @@ export default { name: 'Submenu', mixins: [ Emitter ], - components: { Icon, Drop }, + components: { Icon, Drop, CollapseTransition }, props: { name: { type: [String, Number], diff --git a/src/styles/animation/index.less b/src/styles/animation/index.less index 66033203..116f9b69 100644 --- a/src/styles/animation/index.less +++ b/src/styles/animation/index.less @@ -25,4 +25,8 @@ @import "fade"; @import "move"; @import "ease"; -@import "slide"; \ No newline at end of file +@import "slide"; + +.collapse-transition { + transition: @transition-time height ease-in-out, @transition-time padding-top ease-in-out, @transition-time padding-bottom ease-in-out; +} \ No newline at end of file diff --git a/src/utils/assist.js b/src/utils/assist.js index daabffd7..71ece1cf 100644 --- a/src/utils/assist.js +++ b/src/utils/assist.js @@ -232,4 +232,66 @@ function findComponentsDownward (context, componentName, components = []) { } return components; } -export {findComponentsDownward}; \ No newline at end of file +export {findComponentsDownward}; + +/* istanbul ignore next */ +const trim = function(string) { + return (string || '').replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, ''); +}; + +/* istanbul ignore next */ +export function hasClass(el, cls) { + if (!el || !cls) return false; + if (cls.indexOf(' ') !== -1) throw new Error('className should not contain space.'); + if (el.classList) { + return el.classList.contains(cls); + } else { + return (' ' + el.className + ' ').indexOf(' ' + cls + ' ') > -1; + } +} + +/* istanbul ignore next */ +export function addClass(el, cls) { + if (!el) return; + let curClass = el.className; + const classes = (cls || '').split(' '); + + for (let i = 0, j = classes.length; i < j; i++) { + const clsName = classes[i]; + if (!clsName) continue; + + if (el.classList) { + el.classList.add(clsName); + } else { + if (!hasClass(el, clsName)) { + curClass += ' ' + clsName; + } + } + } + if (!el.classList) { + el.className = curClass; + } +} + +/* istanbul ignore next */ +export function removeClass(el, cls) { + if (!el || !cls) return; + const classes = cls.split(' '); + let curClass = ' ' + el.className + ' '; + + for (let i = 0, j = classes.length; i < j; i++) { + const clsName = classes[i]; + if (!clsName) continue; + + if (el.classList) { + el.classList.remove(clsName); + } else { + if (hasClass(el, clsName)) { + curClass = curClass.replace(' ' + clsName + ' ', ' '); + } + } + } + if (!el.classList) { + el.className = trim(curClass); + } +} \ No newline at end of file