8000 simplify watcher · sinabio/vue@c0d22e8 · GitHub
[go: up one dir, main page]

Skip to content

Commit c0d22e8

Browse files
committed
simplify watcher
1 parent 09c8877 commit c0d22e8

File tree

12 files changed

+40
-191
lines changed

12 files changed

+40
-191
lines changed

src/api/data.js

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -70,28 +70,18 @@ exports.$delete = function (key) {
7070

7171
exports.$watch = function (exp, cb, deep, immediate) {
7272
var vm = this
73-
var key = deep ? exp + '**deep**' : exp
74-
var watcher = vm._userWatchers[key]
7573
var wrappedCb = function (val, oldVal) {
7674
cb.call(vm, val, oldVal)
7775
}
78-
if (!watcher) {
79-
watcher = vm._userWatchers[key] =
80-
new Watcher(vm, exp, wrappedCb, {
81-
deep: deep,
82-
user: true
83-
})
84-
} else {
85-
watcher.addCb(wrappedCb)
86-
}
76+
var watcher = new Watcher(vm, exp, wrappedCb, {
77+
deep: deep,
78+
user: true
79+
})
8780
if (immediate) {
8881
wrappedCb(watcher.value)
8982
}
9083
return function unwatchFn () {
91-
watcher.removeCb(wrappedCb)
92-
if (!watcher.active) {
93-
vm._userWatchers[key] = null
94-
}
84+
watcher.teardown()
9585
}
9686
}
9787

src/directive.js

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -78,27 +78,16 @@ p._bind = function (def) {
7878
}
7979
}
8080
: function () {} // noop if no update is provided
81-
// use raw expression as identifier because filters
82-
// make them different watchers
83-
var watcher = this.vm._watchers[this.raw]
84-
// v-repeat always creates a new watcher because it has
85-
// a special filter that's bound to its directive
86-
// instance.
87-
if (!watcher || this.name === 'repeat') {
88-
watcher = this.vm._watchers[this.raw] = new Watcher(
89-
this.vm,
90-
this._watcherExp,
91-
update, // callback
92-
{
93-
filters: this.filters,
94-
twoWay: this.twoWay,
95-
deep: this.deep
96-
}
97-
)
98-
} else {
99-
watcher.addCb(update)
100-
}
101-
this._watcher = watcher
81+
var watcher = this._watcher = new Watcher(
82+
this.vm,
83+
this._watcherExp,
84+
update, // callback
85+
{
86+
filters: this.filters,
87+
twoWay: this.twoWay,
88+
deep: this.deep
89+
}
90+
)
10291
if (this._initValue != null) {
10392
watcher.set(this._initValue)
10493
} else if (this.update) {
@@ -182,17 +171,13 @@ p._checkParam = function (name) {
182171

183172
p._teardown = function () {
184173
if (this._bound) {
174+
this._bound = false
185175
if (this.unbind) {
186176
this.unbind()
187177
}
188-
var watcher = this._watcher
189-
if (watcher && watcher.active) {
190-
watcher.removeCb(this._update)
191-
if (!watcher.active) {
192-
this.vm._watchers[this.raw] = null
193-
}
178+
if (this._watcher) {
179+
this._watcher.teardown()
194180
}
195-
this._bound = false
196181
this.vm = this.el = this._watcher = null
197182
}
198183
}

src/instance/compile.js

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,9 @@ exports._destroy = function (remove, deferCleanup) {
118118
// splicing the directives
119119
this._unlinkFn(true)
120120
}
121-
// teardown all user watchers.
122-
var watcher
123-
for (i in this._userWatchers) {
124-
watcher = this._userWatchers[i]
125-
if (watcher) {
126-
watcher.teardown()
127-
}
121+
i = this._watchers.length
122+
while (i--) {
123+
this._watchers[i].teardown()
128124
}
129125
// remove reference to self on $el
130126
if (this.$el) {
@@ -152,8 +148,6 @@ exports._cleanup = function () {
152148
this._data.__ob__.removeVm(this)
153149
this._data =
154150
this._watchers =
155-
this._userWatchers =
156-
this._watcherList =
157151
this.$el =
158152
this.$parent =
159153
this.$root =

src/instance/init.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@ exports._init = function (options) {
2020
this.$root = options._root || this
2121
this.$ = {} // child vm references
2222
this.$$ = {} // element references
23-
this._watcherList = [] // all watchers as an array
24-
this._watchers = {} // internal watchers as a hash
25-
this._userWatchers = {} // user watchers as a hash
23+
this._watchers = [] // all watchers as an array
2624
this._directives = [] // all directives
2725

2826
// a flag to avoid this being observed

src/instance/scope.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,9 @@ exports._unproxy = function (key) {
123123
*/
124124

125125
exports._digest = function () {
126-
var i = this._watcherList.length
126+
var i = this._watchers.length
127127
while (i--) {
128-
this._watcherList[i].update()
128+
this._watchers[i].update()
129129
}
130130
var children = this._children
131131
i = children.length

src/watcher.js

Lines changed: 6 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,15 @@ var uid = 0
2323

2424
function Watcher (vm, expression, cb, options) {
2525
this.vm = vm
26-
vm._watcherList.push(this)
26+
vm._watchers.push(this)
2727
this.expression = expression
28-
this.cbs = [cb]
28+
this.cb = cb
2929
this.id = ++uid // uid for batching
3030
this.active = true
3131
options = options || {}
3232
this.deep = !!options.deep
3333
this.user = !!options.user
34+
this.twoWay = !!options.twoWay
3435
this.deps = []
3536
this.newDeps = []
3637
// setup filters if any.
@@ -174,46 +175,11 @@ p.run = function () {
174175
) {
175176
var oldValue = this.value
176177
this.value = value
177-
var cbs = this.cbs
178-
for (var i = 0, l = cbs.length; i < l; i++) {
179-
cbs[i](value, oldValue)
180-
// if a callback also removed other callbacks,
181-
// we need to adjust the loop accordingly.
182-
var removed = l - cbs.length
183-
if (removed) {
184-
i -= removed
185-
l -= removed
186-
}
187-
}
178+
this.cb(value, oldValue)
188179
}
189180
}
190181
}
191182

192-
/**
193-
* Add a callback.
194-
*
195-
* @param {Function} cb
196-
*/
197-
198-
p.addCb = function (cb) {
199-
this.cbs.push(cb)
200-
}
201-
202-
/**
203-
* Remove a callback.
204-
*
205-
* @param {Function} cb
206-
*/
207-
208-
p.removeCb = function (cb) {
209-
var cbs = this.cbs
210-
if (cbs.length > 1) {
211-
cbs.$remove(cb)
212-
} else if (cb === cbs[0]) {
213-
this.teardown()
214-
}
215-
}
216-
217183
/**
218184
* Remove self from all dependencies' subcriber list.
219185
*/
@@ -224,14 +190,14 @@ p.teardown = function () {
224190
// we can skip this if the vm if being destroyed
225191
// which can improve teardown performance.
226192
if (!this.vm._isBeingDestroyed) {
227-
this.vm._watcherList.$remove(this)
193+
this.vm._watchers.$remove(this)
228194
}
229195
var i = this.deps.length
230196
while (i--) {
231197
this.deps[i].removeSub(this)
232198
}
233199
this.active = false
234-
this.vm = this.cbs = this.value = null
200+
this.vm = this.cb = this.value = null
235201
}
236202
}
237203

test/unit/specs/api/data_spec.js

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -89,23 +89,12 @@ describe('Data API', function () {
8989
vm.a = 2
9090
nextTick(function () {
9191
expect(spy).toHaveBeenCalledWith(4, 3)
92-
// reuse same watcher
93-
var spy2 = jasmine.createSpy()
94-
var unwatch2 = vm.$watch('a + b.c', spy2)
95-
expect(vm._watcherList.length).toBe(1)
96-
vm.b = { c: 3 }
92+
// unwatch
93+
unwatch()
94+
vm.a = 3
9795
nextTick(function () {
98-
expect(spy).toHaveBeenCalledWith(5, 4)
99-
expect(spy2).toHaveBeenCalledWith(5, 4)
100-
// unwatch
101-
unwatch()
102-
unwatch2()
103-
vm.a = 3
104-
nextTick(function () {
105-
expect(spy.calls.count()).toBe(3)
106-
expect(spy2.calls.count()).toBe(1)
107-
done()
108-
})
96+
expect(spy.calls.count()).toBe(2)
97+
done()
10998
})
11099
})
111100
})

test/unit/specs/api/lifecycle_spec.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,6 @@ if (_.inBrowser) {
161161
expect(data.__ob__.vms.length).toBe(0)
162162
expect(vm._isDestroyed).toBe(true)
163163
expect(vm._watchers).toBeNull()
164-
expect(vm._userWatchers).toBeNull()
165-
expect(vm._watcherList).toBeNull()
166164
expect(vm.$el).toBeNull()
167165
expect(vm.$parent).toBeNull()
168166
expect(vm.$root).toBeNull()
@@ -236,8 +234,8 @@ if (_.inBrowser) {
236234
data: { a: 1 }
237235
})
238236
vm.$watch('a', function () {})
239-
var dirWatcher = vm._watcherList[0]
240-
var userWatcher = vm._watcherList[1]
237+
var dirWatcher = vm._watchers[0]
238+
var userWatcher = vm._watchers[1]
241239
vm.$destroy()
242240
expect(dirWatcher.active).toBe(false)
243241
expect(userWatcher.active).toBe(false)

test/unit/specs/directive_spec.js

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -162,25 +162,4 @@ describe('Directive', function () {
162162
expect(def.update).toHaveBeenCalled()
163163
})
164164

165-
it('reuse the same watcher', function (done) {
166-
var d = new Directive('test', el, vm, {
167-
expression: 'a',
168-
}, def)
169-
var d2 = new Directive('test', el, vm, {
170-
expression: 'a',
171-
}, def)
172-
expect(vm._watcherList.length).toBe(1)
173-
expect(d._watcher).toBe(d2._watcher)
174-
d2._teardown()
175-
expect(d2._watcher).toBeNull()
176-
expect(vm._watcherList.length).toBe(1)
177-
vm.a = 2
178-
nextTick(function () {
179-
expect(def.update).toHaveBeenCalledWith(2, 1)
180-
d._teardown()
181-
expect(vm._watcherList.length).toBe(0)
182-
done()
183-
})
184-
})
185-
186165
})

test/unit/specs/directives/model_spec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,9 +232,9 @@ if (_.inBrowser) {
232232
expect(opts[0].selected).toBe(true)
233233
expect(opts[1].selected).toBe(false)
234234
// should teardown option watcher when unbind
235-
expect(vm._watcherList.length).toBe(2)
235+
expect(vm._watchers.length).toBe(2)
236236
vm._directives[0]._teardown()
237-
expect(vm._watcherList.length).toBe(0)
237+
expect(vm._watchers.length).toBe(0)
238238
done()
239239
})
240240
})

0 commit comments

Comments
 (0)
0