Selaa lähdekoodia

perf optimization for watcher dep collection

Evan You 11 vuotta sitten
vanhempi
commit
30bd8be797
5 muutettua tiedostoa jossa 43 lisäystä ja 18 poistoa
  1. 1 1
      src/directives/repeat.js
  2. 1 1
      src/observer/array.js
  3. 0 2
      src/observer/dep.js
  4. 22 2
      src/util/lang.js
  5. 19 12
      src/watcher.js

+ 1 - 1
src/directives/repeat.js

@@ -406,7 +406,7 @@ module.exports = {
           )
         }
       } else {
-        _.define(data, this.id, vm)
+        _.define(data, id, vm)
       }
     } else {
       if (!cache[data]) {

+ 1 - 1
src/observer/array.js

@@ -81,7 +81,7 @@ _.define(
     /* istanbul ignore if */
     if (!this.length) return
     if (typeof index !== 'number') {
-      index = this.indexOf(index)
+      index = _.indexOf(this, index)
     }
     if (index > -1) {
       this.splice(index, 1)

+ 0 - 2
src/observer/dep.js

@@ -1,4 +1,3 @@
-var uid = 0
 var _ = require('../util')
 
 /**
@@ -9,7 +8,6 @@ var _ = require('../util')
  */
 
 function Dep () {
-  this.id = ++uid
   this.subs = []
 }
 

+ 22 - 2
src/util/lang.js

@@ -105,8 +105,13 @@ exports.classify = function (str) {
  */
 
 exports.bind = function (fn, ctx) {
-  return function () {
-    return fn.apply(ctx, arguments)
+  return function (a) {
+    var l = arguments.length
+    return l
+      ? l > 1
+        ? fn.apply(ctx, arguments)
+        : fn.call(ctx, a)
+      : fn.call(ctx)
   }
 }
 
@@ -227,4 +232,19 @@ exports.debounce = function(func, wait) {
     }
     return result
   }
+}
+
+/**
+ * Manual indexOf because it's slightly faster than
+ * native.
+ *
+ * @param {Array} arr
+ * @param {*} obj
+ */
+
+exports.indexOf = function (arr, obj) {
+  for (var i = 0, l = arr.length; i < l; i++) {
+    if (arr[i] === obj) return i
+  }
+  return -1
 }

+ 19 - 12
src/watcher.js

@@ -31,7 +31,8 @@ function Watcher (vm, expression, cb, options) {
   options = options || {}
   this.deep = !!options.deep
   this.user = !!options.user
-  this.deps = Object.create(null)
+  this.deps = []
+  this.newDeps = []
   // setup filters if any.
   // We delegate directive filters here to the watcher
   // because they need to be included in the dependency
@@ -56,12 +57,15 @@ var p = Watcher.prototype
  */
 
 p.addDep = function (dep) {
-  var id = dep.id
-  if (!this.newDeps[id]) {
-    this.newDeps[id] = dep
-    if (!this.deps[id]) {
-      this.deps[id] = dep
+  var newDeps = this.newDeps
+  var old = this.deps
+  if (_.indexOf(newDeps, dep) < 0) {
+    newDeps.push(dep)
+    var i = _.indexOf(old, dep)
+    if (i < 0) {
       dep.addSub(this)
+    } else {
+      old[i] = null
     }
   }
 }
@@ -123,7 +127,6 @@ p.set = function (value) {
 
 p.beforeGet = function () {
   Observer.target = this
-  this.newDeps = {}
 }
 
 /**
@@ -132,12 +135,15 @@ p.beforeGet = function () {
 
 p.afterGet = function () {
   Observer.target = null
-  for (var id in this.deps) {
-    if (!this.newDeps[id]) {
-      this.deps[id].removeSub(this)
+  var i = this.deps.length
+  while (i--) {
+    var dep = this.deps[i]
+    if (dep) {
+      dep.removeSub(this)
     }
   }
   this.deps = this.newDeps
+  this.newDeps = []
 }
 
 /**
@@ -220,8 +226,9 @@ p.teardown = function () {
     if (!this.vm._isBeingDestroyed) {
       this.vm._watcherList.$remove(this)
     }
-    for (var id in this.deps) {
-      this.deps[id].removeSub(this)
+    var i = this.deps.length
+    while (i--) {
+      this.deps[i].removeSub(this)
     }
     this.active = false
     this.vm = this.cbs = this.value = null