mirror of
https://gitee.com/vuejs/vue.git
synced 2024-12-04 21:17:55 +08:00
basic transition tests
This commit is contained in:
parent
9c2ca07cc6
commit
74538b4529
@ -1,26 +1,8 @@
|
||||
/* @flow */
|
||||
|
||||
import { isIE9, namespaceMap } from 'web/util/index'
|
||||
|
||||
const svgNS = namespaceMap.svg
|
||||
|
||||
/**
|
||||
* In IE9, setAttribute('class') will result in empty class
|
||||
* if the element also has the :class attribute; However in
|
||||
* PhantomJS, setting `className` does not work on SVG elements...
|
||||
* So we have to do a conditional check here.
|
||||
*/
|
||||
export function setClass (el: Element, cls: string) {
|
||||
/* istanbul ignore else */
|
||||
if (!isIE9 || el.namespaceURI === svgNS) {
|
||||
el.setAttribute('class', cls)
|
||||
} else {
|
||||
el.className = cls
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add class with compatibility for IE & SVG
|
||||
* Add class with compatibility for SVG since classList is not supported on
|
||||
* SVG elements in IE
|
||||
*/
|
||||
export function addClass (el: Element, cls: string) {
|
||||
if (el.classList) {
|
||||
@ -30,15 +12,16 @@ export function addClass (el: Element, cls: string) {
|
||||
el.classList.add(cls)
|
||||
}
|
||||
} else {
|
||||
const cur = ' ' + getClass(el) + ' '
|
||||
const cur = ' ' + el.getAttribute('class') + ' '
|
||||
if (cur.indexOf(' ' + cls + ' ') < 0) {
|
||||
setClass(el, (cur + cls).trim())
|
||||
el.setAttribute('class', (cur + cls).trim())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove class with compatibility for IE & SVG
|
||||
* Remove class with compatibility for SVG since classList is not supported on
|
||||
* SVG elements in IE
|
||||
*/
|
||||
export function removeClass (el: Element, cls: string) {
|
||||
if (el.classList) {
|
||||
@ -48,27 +31,11 @@ export function removeClass (el: Element, cls: string) {
|
||||
el.classList.remove(cls)
|
||||
}
|
||||
} else {
|
||||
let cur = ' ' + getClass(el) + ' '
|
||||
let cur = ' ' + el.getAttribute('class') + ' '
|
||||
const tar = ' ' + cls + ' '
|
||||
while (cur.indexOf(tar) >= 0) {
|
||||
cur = cur.replace(tar, ' ')
|
||||
}
|
||||
setClass(el, cur.trim())
|
||||
}
|
||||
if (!el.className) {
|
||||
el.removeAttribute('class')
|
||||
el.setAttribute('class', cur.trim())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For IE9 compat: when both class and :class are present
|
||||
* getAttribute('class') returns wrong value... but className
|
||||
* on SVG elements returns an object.
|
||||
*/
|
||||
function getClass (el: Element): string {
|
||||
let classname = el.className
|
||||
if (typeof classname === 'object') {
|
||||
classname = classname.baseVal || ''
|
||||
}
|
||||
return classname
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* @flow */
|
||||
|
||||
import { setClass } from '../class-util'
|
||||
import { genClassForVnode, concat, stringifyClass } from 'web/util/index'
|
||||
|
||||
function updateClass (oldVnode: any, vnode: any) {
|
||||
@ -20,7 +19,7 @@ function updateClass (oldVnode: any, vnode: any) {
|
||||
|
||||
// set the class
|
||||
if (cls !== el._prevClass) {
|
||||
setClass(el, cls)
|
||||
el.setAttribute('class', cls)
|
||||
el._prevClass = cls
|
||||
}
|
||||
}
|
||||
|
@ -10,11 +10,12 @@ const TRANSITION = 'transition'
|
||||
const ANIMATION = 'animation'
|
||||
|
||||
// Transition property/event sniffing
|
||||
let transitionProp = 'transition'
|
||||
let transitionEndEvent = 'transitionend'
|
||||
let animationProp = 'animation'
|
||||
let animationEndEvent = 'animationend'
|
||||
export let transitionProp = 'transition'
|
||||
export let transitionEndEvent = 'transitionend'
|
||||
export let animationProp = 'animation'
|
||||
export let animationEndEvent = 'animationend'
|
||||
if (hasTransition) {
|
||||
/* istanbul ignore if */
|
||||
if (window.ontransitionend === undefined &&
|
||||
window.onwebkittransitionend !== undefined) {
|
||||
transitionProp = 'WebkitTransition'
|
||||
@ -28,7 +29,7 @@ if (hasTransition) {
|
||||
}
|
||||
|
||||
const raf = (inBrowser && window.requestAnimationFrame) || setTimeout
|
||||
function nextFrame (fn) {
|
||||
export function nextFrame (fn: Function) {
|
||||
raf(() => {
|
||||
raf(fn)
|
||||
})
|
||||
|
@ -20,7 +20,7 @@ window.waitForUpdate = initialCb => {
|
||||
if (queue.length) {
|
||||
let hasError = false
|
||||
try {
|
||||
job()
|
||||
job.wait ? job(shift) : job()
|
||||
} catch (e) {
|
||||
hasError = true
|
||||
const done = queue[queue.length - 1]
|
||||
@ -28,7 +28,7 @@ window.waitForUpdate = initialCb => {
|
||||
done.fail(e)
|
||||
}
|
||||
}
|
||||
if (!hasError) {
|
||||
if (!hasError && !job.wait) {
|
||||
if (queue.length) {
|
||||
Vue.nextTick(shift)
|
||||
}
|
||||
@ -49,6 +49,11 @@ window.waitForUpdate = initialCb => {
|
||||
then: nextCb => {
|
||||
queue.push(nextCb)
|
||||
return chainer
|
||||
},
|
||||
thenWaitFor: (wait) => {
|
||||
wait.wait = true
|
||||
queue.push(wait)
|
||||
return chainer
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,79 @@
|
||||
import Vue from 'vue'
|
||||
import { isIE9 } from 'web/util/index'
|
||||
import { nextFrame } from 'web/runtime/modules/transition'
|
||||
|
||||
if (!isIE9) {
|
||||
describe('Transition CSS', () => {
|
||||
const duration = 50
|
||||
insertCSS(`
|
||||
.test {
|
||||
-webkit-transition: opacity ${duration}ms ease;
|
||||
transition: opacity ${duration}ms ease;
|
||||
}
|
||||
.test-enter, .test-leave-active {
|
||||
opacity: 0;
|
||||
}
|
||||
.test-anim-enter {
|
||||
animation: test-enter ${duration}ms;
|
||||
-webkit-animation: test-enter ${duration}ms;
|
||||
}
|
||||
.test-anim-leave {
|
||||
animation: test-leave ${duration}ms;
|
||||
-webkit-animation: test-leave ${duration}ms;
|
||||
}
|
||||
@keyframes test-enter {
|
||||
from { opacity: 0 }
|
||||
to { opacity: 1 }
|
||||
}
|
||||
@-webkit-keyframes test-enter {
|
||||
from { opacity: 0 }
|
||||
to { opacity: 1 }
|
||||
}
|
||||
@keyframes test-leave {
|
||||
from { opacity: 1 }
|
||||
to { opacity: 0 }
|
||||
}
|
||||
@-webkit-keyframes test-leave {
|
||||
from { opacity: 1 }
|
||||
to { opacity: 0 }
|
||||
}
|
||||
`)
|
||||
|
||||
it('basic transitions', done => {
|
||||
const el = document.createElement('div')
|
||||
document.body.appendChild(el)
|
||||
const vm = new Vue({
|
||||
template: '<div><div v-if="ok" class="test" transition="test">foo</div></div>',
|
||||
data: { ok: true }
|
||||
}).$mount(el)
|
||||
|
||||
// should not apply transition on initial render by default
|
||||
expect(vm.$el.innerHTML).toBe('<div class="test">foo</div>')
|
||||
vm.ok = false
|
||||
waitForUpdate(() => {
|
||||
expect(vm.$el.children[0].className).toBe('test test-leave')
|
||||
}).thenWaitFor(nextFrame).then(() => {
|
||||
expect(vm.$el.children[0].className).toBe('test test-leave-active')
|
||||
}).thenWaitFor(timeout(duration + 1)).then(() => {
|
||||
expect(vm.$el.children.length).toBe(0)
|
||||
vm.ok = true
|
||||
}).then(() => {
|
||||
expect(vm.$el.children[0].className).toBe('test test-enter')
|
||||
}).thenWaitFor(nextFrame).then(() => {
|
||||
expect(vm.$el.children[0].className).toBe('test test-enter-active')
|
||||
}).thenWaitFor(timeout(duration + 1)).then(() => {
|
||||
expect(vm.$el.children[0].className).toBe('test')
|
||||
}).then(done)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function insertCSS (text) {
|
||||
var cssEl = document.createElement('style')
|
||||
cssEl.textContent = text.trim()
|
||||
document.head.appendChild(cssEl)
|
||||
}
|
||||
|
||||
function timeout (n) {
|
||||
return next => setTimeout(next, n)
|
||||
}
|
Loading…
Reference in New Issue
Block a user