Преглед изворни кода

further performance tuning for v-for re-render

Evan You пре 10 година
родитељ
комит
cba32f4d95
3 измењених фајлова са 19 додато и 5 уклоњено
  1. 6 0
      src/directives/public/for.js
  2. 2 1
      src/instance/internal/init.js
  3. 11 4
      src/watcher.js

+ 6 - 0
src/directives/public/for.js

@@ -164,6 +164,10 @@ const vFor = {
     // from cache)
     var removalIndex = 0
     var totalRemoved = oldFrags.length - frags.length
+    // when removing a large number of fragments, watcher removal
+    // turns out to be a perf bottleneck, so we batch the watcher
+    // removals into a single filter call!
+    this.vm._vForRemoving = true
     for (i = 0, l = oldFrags.length; i < l; i++) {
       frag = oldFrags[i]
       if (!frag.reused) {
@@ -171,6 +175,8 @@ const vFor = {
         this.remove(frag, removalIndex++, totalRemoved, inDocument)
       }
     }
+    this.vm._vForRemoving = false
+    this.vm._watchers = this.vm._watchers.filter(w => w.active)
 
     // Final pass, move/insert new fragments into the
     // right place.

+ 2 - 1
src/instance/internal/init.js

@@ -51,7 +51,8 @@ export default function (Vue) {
     this._isDestroyed =
     this._isReady =
     this._isAttached =
-    this._isBeingDestroyed = false
+    this._isBeingDestroyed =
+    this._vForRemoving = false
     this._unlinkFn = null
 
     // context:

+ 11 - 4
src/watcher.js

@@ -1,8 +1,14 @@
-import { extend, warn, isArray, isObject, nextTick } from './util/index'
 import config from './config'
 import Dep from './observer/dep'
 import { parseExpression } from './parsers/expression'
 import { pushWatcher } from './batcher'
+import {
+  extend,
+  warn,
+  isArray,
+  isObject,
+  nextTick
+} from './util/index'
 
 let uid = 0
 
@@ -299,9 +305,10 @@ Watcher.prototype.depend = function () {
 Watcher.prototype.teardown = function () {
   if (this.active) {
     // remove self from vm's watcher list
-    // we can skip this if the vm if being destroyed
-    // which can improve teardown performance.
-    if (!this.vm._isBeingDestroyed) {
+    // this is a somewhat expensive operation so we skip it
+    // if the vm is being destroyed or is performing a v-for
+    // re-render (the watcher list is then filtered by v-for).
+    if (!this.vm._isBeingDestroyed && !this.vm._vForRemoving) {
       this.vm._watchers.$remove(this)
     }
     var depIds = Object.keys(this.deps)