Просмотр исходного кода

do the forced layout on next frame in transitions

Evan You 11 лет назад
Родитель
Сommit
2fb9660eb9
3 измененных файлов с 40 добавлено и 27 удалено
  1. 1 3
      package.json
  2. 6 0
      src/batcher.js
  3. 33 24
      src/transition/css.js

+ 1 - 3
package.json

@@ -34,9 +34,7 @@
     "karma-coverage": "^0.2.5",
     "karma-firefox-launcher": "^0.1.3",
     "karma-jasmine": "^0.2.2",
-    "karma-phantomjs-launcher": "^0.1.4"
-  },
-  "dependencies": {
+    "karma-phantomjs-launcher": "^0.1.4",
     "uglify-js": "^2.4.15"
   }
 }

+ 6 - 0
src/batcher.js

@@ -6,6 +6,7 @@ var _ = require('./util')
  */
 
 function Batcher () {
+  this._preFlush = null
   this.reset()
 }
 
@@ -41,9 +42,14 @@ p.push = function (job) {
 
 /**
  * Flush the queue and run the jobs.
+ * Will call a preFlush hook if has one.
  */
 
 p.flush = function () {
+  // before flush hook
+  if (this._preFlush) {
+    this._preFlush()
+  }
   // do not cache length because more jobs might be pushed
   // as we run existing jobs
   for (var i = 0; i < this.queue.length; i++) {

+ 33 - 24
src/transition/css.js

@@ -1,22 +1,16 @@
 var _ = require('../util')
+var Batcher = require('../batcher')
+var batcher = new Batcher()
 var transDurationProp = _.transitionProp + 'Duration'
 var animDurationProp = _.animationProp + 'Duration'
 
 /**
- * Force layout before triggering transitions/animations.
- * This function ensures we only do it once per event loop.
+ * Force layout before triggering transitions/animations
  */
 
-var forcedLayout = false
-function forceLayout () {
-  if (!forcedLayout) {
-    /* jshint unused: false */
-    var f = document.documentElement.offsetHeight
-    forcedLayout = true
-    _.nextTick(function () {
-      forcedLayout = false
-    })
-  }
+batcher._preFlush = function () {
+  /* jshint unused: false */
+  var f = document.documentElement.offsetHeight
 }
 
 /**
@@ -24,27 +18,36 @@ function forceLayout () {
  * calculated styles
  *
  * @param {Element} el
+ * @param {Object} data
+ * @param {String} className
  * @return {Number}
  *         1 - transition
  *         2 - animation
  */
 
-function getTransitionType (el) {
+function getTransitionType (el, data, className) {
+  var type = data.cache && data.cache[className]
+  if (type) return type
   var inlineStyles = el.style
   var computedStyles = window.getComputedStyle(el)
   var transDuration =
     inlineStyles[transDurationProp] ||
     computedStyles[transDurationProp]
   if (transDuration && transDuration !== '0s') {
-    return 1
+    type = 1
   } else {
     var animDuration =
       inlineStyles[animDurationProp] ||
       computedStyles[animDurationProp]
     if (animDuration && animDuration !== '0s') {
-      return 2
+      type = 2
     }
   }
+  if (type) {
+    if (!data.cache) data.cache = {}
+    data.cache[className] = type
+  }
+  return type
 }
 
 /**
@@ -73,10 +76,13 @@ module.exports = function (el, direction, op, data, cb) {
     // Enter Transition
     classList.add(enterClass)
     op()
-    transitionType = getTransitionType(el)
+    transitionType = getTransitionType(el, data, enterClass)
     if (transitionType === 1) {
-      forceLayout()
-      classList.remove(enterClass)
+      batcher.push({
+        run: function () {
+          classList.remove(enterClass)
+        }
+      })
       // only listen for transition end if user has sent
       // in a callback
       if (cb) {
@@ -114,14 +120,17 @@ module.exports = function (el, direction, op, data, cb) {
 
   } else { // leave
 
-    // we need to add the class here before we can sniff
-    // the transition type, and before that we need to
-    // force a layout so the element picks up all transition
-    // css rules.
-    forceLayout()
     classList.add(leaveClass)
-    transitionType = getTransitionType(el)
+    transitionType = getTransitionType(el, data, leaveClass)
     if (transitionType) {
+      if (transitionType === 1) {
+        classList.remove(leaveClass)
+        batcher.push({
+          run: function () {
+            classList.add(leaveClass)
+          }
+        })
+      }
       endEvent = data.event = transitionType === 1
         ? _.transitionEndEvent
         : _.animationEndEvent