Skip to content

Commit b4cf8bb

Browse files
committed
$index & $key are now meta properties and no longer stored in data, only accessible on the VM
1 parent e54413d commit b4cf8bb

File tree

2 files changed

+63
-38
lines changed

2 files changed

+63
-38
lines changed

src/compiler.js

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ CompilerProto.observeData = function (data) {
262262
$dataBinding.update(data)
263263

264264
// allow $data to be swapped
265-
Object.defineProperty(compiler.vm, '$data', {
265+
defGetSet(compiler.vm, '$data', {
266266
enumerable: false,
267267
get: function () {
268268
compiler.observer.emit('get', '$data')
@@ -562,9 +562,11 @@ CompilerProto.createBinding = function (key, isExp, isFn) {
562562
if (computed && computed[key]) {
563563
// computed property
564564
compiler.defineComputed(key, binding, computed[key])
565-
} else {
565+
} else if (key.charAt(0) !== '$') {
566566
// normal property
567567
compiler.defineProp(key, binding)
568+
} else {
569+
compiler.defineMeta(key, binding)
568570
}
569571
} else {
570572
// ensure path in data so it can be observed
@@ -604,7 +606,7 @@ CompilerProto.defineProp = function (key, binding) {
604606

605607
binding.value = data[key]
606608

607-
Object.defineProperty(compiler.vm, key, {
609+
defGetSet(compiler.vm, key, {
608610
get: function () {
609611
return compiler.data[key]
610612
},
@@ -614,6 +616,27 @@ CompilerProto.defineProp = function (key, binding) {
614616
})
615617
}
616618

619+
/**
620+
* Define a meta property, e.g. $index or $key,
621+
* which is bindable but only accessible on the VM,
622+
* not in the data.
623+
*/
624+
CompilerProto.defineMeta = function (key, binding) {
625+
var vm = this.vm,
626+
ob = this.observer,
627+
value = binding.value = vm[key] || this.data[key]
628+
defGetSet(vm, key, {
629+
get: function () {
630+
if (Observer.shouldGet) ob.emit('get', key)
631+
return value
632+
},
633+
set: function (val) {
634+
ob.emit('set', key, val)
635+
value = val
636+
}
637+
})
638+
}
639+
617640
/**
618641
* Define an expression binding, which is essentially
619642
* an anonymous computed property
@@ -631,7 +654,7 @@ CompilerProto.defineExp = function (key, binding) {
631654
*/
632655
CompilerProto.defineComputed = function (key, binding, value) {
633656
this.markComputed(binding, value)
634-
Object.defineProperty(this.vm, key, {
657+
defGetSet(this.vm, key, {
635658
get: binding.value.$get,
636659
set: binding.value.$set
637660
})
@@ -832,4 +855,11 @@ function getRoot (compiler) {
832855
return compiler
833856
}
834857

858+
/**
859+
* for convenience & minification
860+
*/
861+
function defGetSet (obj, key, def) {
862+
Object.defineProperty(obj, key, def)
863+
}
864+
835865
module.exports = Compiler

src/directives/repeat.js

Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,39 +12,40 @@ var Observer = require('../observer'),
1212
var mutationHandlers = {
1313

1414
push: function (m) {
15-
var l = m.args.length,
15+
var i = 0, l = m.args.length, vm,
1616
base = this.collection.length - l
17-
for (var i = 0; i < l; i++) {
18-
this.buildItem(m.args[i], base + i)
19-
this.updateObject(m.args[i], 1)
17+
for (; i < l; i++) {
18+
vm = this.buildItem(m.args[i], base + i)
19+
this.updateObject(vm, 1)
2020
}
2121
},
2222

2323
pop: function () {
2424
var vm = this.vms.pop()
2525
if (vm) {
2626
vm.$destroy()
27-
this.updateObject(vm.$data, -1)
27+
this.updateObject(vm, -1)
2828
}
2929
},
3030

3131
unshift: function (m) {
32-
for (var i = 0, l = m.args.length; i < l; i++) {
33-
this.buildItem(m.args[i], i)
34-
this.updateObject(m.args[i], 1)
32+
var i = 0, l = m.args.length, vm
33+
for (; i < l; i++) {
34+
vm = this.buildItem(m.args[i], i)
35+
this.updateObject(vm, 1)
3536
}
3637
},
3738

3839
shift: function () {
3940
var vm = this.vms.shift()
4041
if (vm) {
4142
vm.$destroy()
42-
this.updateObject(vm.$data, -1)
43+
this.updateObject(vm, -1)
4344
}
4445
},
4546

4647
splice: function (m) {
47-
var i, l,
48+
var i, l, vm,
4849
index = m.args[0],
4950
removed = m.args[1],
5051
added = m.args.length - 2,
@@ -53,11 +54,11 @@ var mutationHandlers = {
5354
: this.vms.splice(index, removed)
5455
for (i = 0, l = removedVMs.length; i < l; i++) {
5556
removedVMs[i].$destroy()
56-
this.updateObject(removedVMs[i].$data, -1)
57+
this.updateObject(removedVMs[i], -1)
5758
}
5859
for (i = 0; i < added; i++) {
59-
this.buildItem(m.args[i + 2], index + i)
60-
this.updateObject(m.args[i + 2], 1)
60+
vm = this.buildItem(m.args[i + 2], index + i)
61+
this.updateObject(vm, 1)
6162
}
6263
},
6364

@@ -151,7 +152,7 @@ module.exports = {
151152
// update index
152153
var i = arr.length
153154
while (i--) {
154-
arr[i].$index = i
155+
self.vms[i].$index = i
155156
}
156157
}
157158
if (method === 'push' || method === 'unshift' || method === 'splice') {
@@ -264,8 +265,6 @@ module.exports = {
264265
// mark, so it won't be destroyed
265266
item.$reused = true
266267
el = item.$el
267-
// don't forget to update index
268-
data.$index = index
269268
// existing VM's el can possibly be detached by v-if.
270269
// in that case don't insert.
271270
detached = !el.parentNode
@@ -282,8 +281,6 @@ module.exports = {
282281
primitive = true
283282
data = { $value: data }
284283
}
285-
// define index
286-
def(data, '$index', index)
287284

288285
}
289286

@@ -318,6 +315,7 @@ module.exports = {
318315
delegator: ctn
319316
}
320317
})
318+
item.$index = index
321319

322320
if (!data) {
323321
// this is a forced compile for an empty collection.
@@ -327,13 +325,15 @@ module.exports = {
327325
vms.splice(index, 0, item)
328326
// for primitive values, listen for value change
329327
if (primitive) {
330-
data.__emitter__.on('set', function (key, val) {
328+
item.$compiler.observer.on('set', function (key, val) {
331329
if (key === '$value') {
332330
col[item.$index] = val
333331
}
334332
})
335333
}
336334
}
335+
336+
return item
337337
},
338338

339339
/**
@@ -355,18 +355,15 @@ module.exports = {
355355
var self = this
356356
this.updateRepeater = function (key, val) {
357357
if (key.indexOf('.') === -1) {
358-
var i = collection.length, item
358+
var i = self.vms.length, item
359359
while (i--) {
360-
item = collection[i]
360+
item = self.vms[i]
361361
if (item.$key === key) {
362-
if (item !== val && item.$value !== val) {
362+
if (item.$data !== val && item.$value !== val) {
363363
if ('$value' in item) {
364364
item.$value = val
365365
} else {
366-
def(val, '$key', key)
367-
self.lock = true
368-
collection.set(i, val)
369-
self.lock = false
366+
item.$data = val
370367
}
371368
}
372369
break
@@ -380,19 +377,17 @@ module.exports = {
380377
},
381378

382379
/**
383-
* Sync changes in the $repeater Array
380+
* Sync changes from the $repeater Array
384381
* back to the represented Object
385382
*/
386-
updateObject: function (data, action) {
387-
if (this.lock) return
383+
updateObject: function (vm, action) {
388384
var obj = this.object
389-
if (obj && data.$key) {
390-
var key = data.$key,
391-
val = data.$value || data
385+
if (obj && vm.$key) {
386+
var key = vm.$key,
387+
val = vm.$value || vm.$data
392388
if (action > 0) { // new property
393389
// make key ienumerable
394-
delete data.$key
395-
def(data, '$key', key)
390+
delete vm.$data.$key
396391
obj[key] = val
397392
Observer.convert(obj, key)
398393
} else {

0 commit comments

Comments
 (0)