Skip to content

Commit 664e59d

Browse files
committed
new v-if implementation using partial compilation
1 parent 2a18cf0 commit 664e59d

File tree

9 files changed

+61
-76
lines changed

9 files changed

+61
-76
lines changed

src/directives/el.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ module.exports = {
33
isLiteral: true,
44

55
bind: function () {
6-
this.vm._owner.$$[this.expression] = this.el
6+
this.vm.$$[this.expression] = this.el
77
},
88

99
unbind: function () {
10-
this.vm._owner.$$[this.expression] = null
10+
delete this.vm.$$[this.expression]
1111
}
1212

1313
}

src/directives/if.js

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
var _ = require('../util')
2+
var compile = require('../compile/compile')
23
var templateParser = require('../parse/template')
4+
var transition = require('../transition')
35

46
module.exports = {
57

@@ -8,10 +10,16 @@ module.exports = {
810
if (!el.__vue__) {
911
this.ref = document.createComment('v-if')
1012
_.replace(el, this.ref)
11-
this.inserted = false
12-
if (el.tagName === 'TEMPLATE') {
13-
this.el = templateParser.parse(el, true)
14-
}
13+
this.isBlock = el.tagName === 'TEMPLATE'
14+
this.template = this.isBlock
15+
? templateParser.parse(el, true)
16+
: el
17+
// compile the nested partial
18+
this.linker = compile(
19+
this.template,
20+
this.vm.$options,
21+
true
22+
)
1523
} else {
1624
this.invalid = true
1725
_.warn(
@@ -24,29 +32,42 @@ module.exports = {
2432
update: function (value) {
2533
if (this.invalid) return
2634
if (value) {
27-
if (!this.inserted) {
28-
if (!this.childVM) {
29-
this.childVM = this.vm.$addChild({
30-
el: this.el,
31-
data: this.vm._data,
32-
inherit: true,
33-
_anonymous: true
34-
})
35+
this.insert()
36+
} else {
37+
this.unbind()
38+
}
39+
},
40+
41+
insert: function () {
42+
var vm = this.vm
43+
var el = templateParser.clone(this.template)
44+
var ref = this.ref
45+
var decompile = this.linker(vm, el)
46+
if (this.isBlock) {
47+
var blockStart = el.firstChild
48+
this.decompile = function () {
49+
decompile()
50+
var node = blockStart
51+
var next
52+
while (node !== ref) {
53+
next = node.nextSibling
54+
transition.remove(node, vm)
55+
node = next
3556
}
36-
this.childVM.$before(this.ref)
37-
this.inserted = true
3857
}
3958
} else {
40-
if (this.inserted) {
41-
this.childVM.$remove()
42-
this.inserted = false
59+
this.decompile = function () {
60+
decompile()
61+
transition.remove(el, vm)
4362
}
4463
}
64+
transition.before(el, ref, vm)
4565
},
4666

4767
unbind: function () {
48-
if (this.childVM) {
49-
this.childVM.$destroy()
68+
if (this.decompile) {
69+
this.decompile()
70+
this.decompile = null
5071
}
5172
}
5273

src/directives/ref.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ module.exports = {
1111
)
1212
return
1313
}
14-
this.owner = this.vm.$parent._owner
14+
this.owner = this.vm.$parent
1515
this.owner.$[this.expression] = this.vm
1616
},
1717

1818
unbind: function () {
19-
this.owner.$[this.expression] = null
19+
delete this.owner.$[this.expression]
2020
}
2121

2222
}

src/directives/repeat.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ module.exports = {
6464
*/
6565

6666
checkRef: function () {
67-
this.owner = this.vm._owner
6867
var childId = _.attr(this.el, 'ref')
6968
this.childId = childId
7069
? this.vm.$interpolate(childId)
@@ -138,10 +137,10 @@ module.exports = {
138137
this.vms = this.diff(data || [], this.vms)
139138
// update v-ref
140139
if (this.childId) {
141-
this.owner.$[this.childId] = this.vms
140+
this.vm.$[this.childId] = this.vms
142141
}
143142
if (this.elId) {
144-
this.owner.$$[this.elId] = this.vms.map(function (vm) {
143+
this.vm.$$[this.elId] = this.vms.map(function (vm) {
145144
return vm.$el
146145
})
147146
}
@@ -326,7 +325,7 @@ module.exports = {
326325

327326
unbind: function () {
328327
if (this.childId) {
329-
delete this.owner.$[this.childId]
328+
delete this.vm.$[this.childId]
330329
}
331330
if (this.vms) {
332331
var i = this.vms.length

src/instance/init.js

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,6 @@ exports._init = function (options) {
5050
this._childCtors = null // @type {Object} - hash to cache
5151
// child constructors
5252

53-
// anonymous instances are created by v-if
54-
// if an instance is anonymous, its owner will be the
55-
// first non-anonymous parent; otherwise its owner will
56-
// be itself.
57-
this._owner = options._anonymous
58-
? this.$parent._owner
59-
: this
60-
6153
// merge options.
6254
options = this.$options = mergeOptions(
6355
this.constructor.options,

test/unit/specs/directives/el_spec.js

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ if (_.inBrowser) {
1717
})
1818
expect(vm.$$.test).toBeTruthy()
1919
expect(vm.$$.test.id).toBe('test')
20+
vm._directives[0]._teardown()
21+
expect(vm.$$.test).toBeUndefined()
2022
})
2123

2224
it('with v-repeat', function (done) {
@@ -36,17 +38,5 @@ if (_.inBrowser) {
3638
})
3739
})
3840

39-
it('inside v-if', function () {
40-
var vm = new Vue({
41-
el: el,
42-
data: { test: true },
43-
template: '<div v-if="test"><div id="test" v-el="test"></div></div>'
44-
})
45-
expect(vm.$$.test).toBeTruthy()
46-
expect(vm.$$.test.id).toBe('test')
47-
vm._children[0].$destroy()
48-
expect(vm.$$.test).toBeNull()
49-
})
50-
5141
})
5242
}

test/unit/specs/directives/if_spec.js

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,30 @@ if (_.inBrowser) {
1414
var vm = new Vue({
1515
el: el,
1616
data: { test: false, a: 'A' },
17-
template: '<div v-if="test">{{$data.a}}</div>'
17+
template: '<div v-if="test"><div v-component="test"></div></div>',
18+
components: {
19+
test: {
20+
inherit: true,
21+
template: '{{a}}'
22+
}
23+
}
1824
})
1925
// lazy instantitation
2026
expect(el.innerHTML).toBe('<!--v-if-->')
2127
expect(vm._children).toBeNull()
2228
vm.test = true
2329
_.nextTick(function () {
24-
expect(el.innerHTML).toBe('<div>A</div><!--v-if-->')
30+
expect(el.innerHTML).toBe('<div><div>A</div><!--v-component--></div><!--v-if-->')
2531
expect(vm._children.length).toBe(1)
2632
vm.test = false
2733
_.nextTick(function () {
2834
expect(el.innerHTML).toBe('<!--v-if-->')
29-
expect(vm._children.length).toBe(1)
30-
var child = vm._children[0]
35+
expect(vm._children.length).toBe(0)
3136
vm.test = true
3237
_.nextTick(function () {
33-
expect(el.innerHTML).toBe('<div>A</div><!--v-if-->')
38+
expect(el.innerHTML).toBe('<div><div>A</div><!--v-component--></div><!--v-if-->')
3439
expect(vm._children.length).toBe(1)
40+
var child = vm._children[0]
3541
vm.$destroy()
3642
expect(child._isDestroyed).toBe(true)
3743
done()
@@ -48,15 +54,12 @@ if (_.inBrowser) {
4854
})
4955
// lazy instantitation
5056
expect(el.innerHTML).toBe('<!--v-if-->')
51-
expect(vm._children).toBeNull()
5257
vm.test = true
5358
_.nextTick(function () {
5459
expect(el.innerHTML).toBe('<p>A</p><p>B</p><!--v-if-->')
55-
expect(vm._children.length).toBe(1)
5660
vm.test = false
5761
_.nextTick(function () {
5862
expect(el.innerHTML).toBe('<!--v-if-->')
59-
expect(vm._children.length).toBe(1)
6063
done()
6164
})
6265
})

test/unit/specs/directives/ref_spec.js

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ if (_.inBrowser) {
2525
expect(vm.$.test).toBeTruthy()
2626
expect(vm.$.test.$options.id).toBe('test')
2727
vm.$.test.$destroy()
28-
expect(vm.$.test).toBeNull()
28+
expect(vm.$.test).toBeUndefined()
2929
})
3030

3131
it('with v-repeat', function (done) {
@@ -47,19 +47,6 @@ if (_.inBrowser) {
4747
})
4848
})
4949

50-
it('inside v-if', function () {
51-
var vm = new Vue({
52-
el: el,
53-
data: { test: true },
54-
components: components,
55-
template: '<div v-if="test"><div v-component="test" v-ref="test"></div></div>'
56-
})
57-
expect(vm.$.test).toBeTruthy()
58-
expect(vm.$.test.$options.id).toBe('test')
59-
vm.$.test.$destroy()
60-
expect(vm.$.test).toBeNull()
61-
})
62-
6350
it('nested v-repeat', function () {
6451
var vm = new Vue({
6552
el: el,

test/unit/specs/instance/init_spec.js

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@ describe('Instance Init', function () {
1515
var options = {
1616
a: 2,
1717
_anonymous: true,
18-
_parent: {
19-
_owner: {}
20-
},
2118
el: {}
2219
}
2320

@@ -40,10 +37,6 @@ describe('Instance Init', function () {
4037
expect(stub.$options.b).toBe(2)
4138
})
4239

43-
it('should locate owner', function () {
44-
expect(stub._owner).toBe(options._parent._owner)
45-
})
46-
4740
it('should call other init methods', function () {
4841
expect(stub._initEvents).toHaveBeenCalled()
4942
expect(stub._initScope).toHaveBeenCalled()

0 commit comments

Comments
 (0)