Skip to content

Commit 940555f

Browse files
committed
dom: simplify fragment insertion/removal
1 parent d1ab424 commit 940555f

File tree

10 files changed

+60
-96
lines changed

10 files changed

+60
-96
lines changed

src/api/dom.js

Lines changed: 15 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -94,22 +94,20 @@ exports.$remove = function (cb, withTransition) {
9494
// if we are not in document, no need to check
9595
// for transitions
9696
if (!inDoc) withTransition = false
97-
var op
9897
var self = this
9998
var realCb = function () {
10099
if (inDoc) self._callHook('detached')
101100
if (cb) cb()
102101
}
103-
if (
104-
this._isFragment &&
105-
!this._blockFragment.hasChildNodes()
106-
) {
107-
op = withTransition === false
108-
? append
109-
: transition.removeThenAppend
110-
blockOp(this, this._blockFragment, op, realCb)
102+
if (this._isFragment) {
103+
var frag = this._fragment
104+
_.mapNodeRange(this._fragmentStart, this._fragmentEnd, function (node) {
105+
// store nodes in the fragment
106+
frag.appendChild(node)
107+
})
108+
realCb()
111109
} else {
112-
op = withTransition === false
110+
var op = withTransition === false
113111
? remove
114112
: transition.remove
115113
op(this.$el, this, realCb)
@@ -132,16 +130,19 @@ exports.$remove = function (cb, withTransition) {
132130
function insert (vm, target, cb, withTransition, op1, op2) {
133131
target = query(target)
134132
var targetIsDetached = !_.inDoc(target)
135-
var op = withTransition === false || targetIsDetached
136-
? op1
137-
: op2
138133
var shouldCallHook =
139134
!targetIsDetached &&
140135
!vm._isAttached &&
141136
!_.inDoc(vm.$el)
142137
if (vm._isFragment) {
143-
blockOp(vm, target, op, cb)
138+
_.mapNodeRange(vm._fragmentStart, vm._fragmentEnd, function (node) {
139+
op1(node, target)
140+
})
141+
cb && cb()
144142
} else {
143+
var op = withTransition === false || targetIsDetached
144+
? op1
145+
: op2
145146
op(vm.$el, target, vm, cb)
146147
}
147148
if (shouldCallHook) {
@@ -150,28 +151,6 @@ function insert (vm, target, cb, withTransition, op1, op2) {
150151
return vm
151152
}
152153

153-
/**
154-
* Execute a transition operation on a fragment instance,
155-
* iterating through all its block nodes.
156-
*
157-
* @param {Vue} vm
158-
* @param {Node} target
159-
* @param {Function} op
160-
* @param {Function} cb
161-
*/
162-
163-
function blockOp (vm, target, op, cb) {
164-
var current = vm._fragmentStart
165-
var end = vm._fragmentEnd
166-
var next
167-
while (next !== end) {
168-
next = current.nextSibling
169-
op(current, target, vm)
170-
current = next
171-
}
172-
op(end, target, vm, cb)
173-
}
174-
175154
/**
176155
* Check for selectors
177156
*

src/api/lifecycle.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ exports.$mount = function (el) {
2323
el = document.createElement('div')
2424
}
2525
this._compile(el)
26-
this._isCompiled = true
27-
this._callHook('compiled')
2826
this._initDOMHooks()
2927
if (_.inDoc(this.$el)) {
3028
this._callHook('attached')

src/fragment/fragment.js

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ function Fragment (linker, vm, frag, host, scope, parentFrag) {
3131
} else {
3232
this.node = _.createAnchor('fragment-start')
3333
this.end = _.createAnchor('fragment-end')
34-
this.nodes = _.toArray(frag.childNodes)
34+
this.frag = frag
35+
_.prepend(this.node, frag)
36+
frag.appendChild(this.end)
3537
this.before = multiBefore
3638
this.remove = multiRemove
3739
}
@@ -71,11 +73,11 @@ Fragment.prototype.destroy = function () {
7173
* Insert fragment before target, single node version
7274
*
7375
* @param {Node} target
74-
* @param {Boolean} trans
76+
* @param {Boolean} withTransition
7577
*/
7678

77-
function singleBefore (target, trans) {
78-
var method = trans !== false
79+
function singleBefore (target, withTransition) {
80+
var method = withTransition !== false
7981
? transition.before
8082
: _.before
8183
method(this.node, target, this.vm)
@@ -112,13 +114,9 @@ function singleRemove (destroy) {
112114
*/
113115

114116
function multiBefore (target) {
115-
_.before(this.node, target)
116-
var nodes = this.nodes
117-
var vm = this.vm
118-
for (var i = 0, l = nodes.length; i < l; i++) {
119-
_.before(nodes[i], target, vm)
120-
}
121-
_.before(this.end, target)
117+
_.mapNodeRange(this.node, this.end, function (node) {
118+
_.before(node, target)
119+
})
122120
this.inserted = true
123121
if (_.inDoc(this.node)) {
124122
this.callHook(attach)
@@ -132,20 +130,11 @@ function multiBefore (target) {
132130
*/
133131

134132
function multiRemove (destroy) {
133+
var frag = this.frag
135134
var shouldCallRemove = _.inDoc(this.node)
136-
var parent = this.node.parentNode
137-
var node = this.node.nextSibling
138-
var nodes = this.nodes = []
139-
var vm = this.vm
140-
var next
141-
while (node !== this.end) {
142-
nodes.push(node)
143-
next = node.nextSibling
144-
parent.removeChild(node, vm)
145-
node = next
146-
}
147-
parent.removeChild(this.node)
148-
parent.removeChild(this.end)
135+
_.mapNodeRange(this.node, this.end, function (node) {
136+
frag.appendChild(node)
137+
})
149138
this.inserted = false
150139
if (shouldCallRemove) {
151140
this.callHook(detach)

src/instance/init.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,9 @@ exports._init = function (options) {
3636

3737
// fragment instance properties
3838
this._isFragment = false
39-
this._fragmentStart = // @type {CommentNode}
40-
this._fragmentEnd = null // @type {CommentNode}
39+
this._fragment = // @type {DocumentFragment}
40+
this._fragmentStart = // @type {Text|Comment}
41+
this._fragmentEnd = null // @type {Text|Comment}
4142

4243
// lifecycle state
4344
this._isCompiled =

src/instance/lifecycle.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ exports._compile = function (el) {
6565
_.replace(original, el)
6666
}
6767

68+
this._isCompiled = true
69+
this._callHook('compiled')
6870
return el
6971
}
7072

@@ -84,7 +86,7 @@ exports._initElement = function (el) {
8486
if (this._fragmentStart.nodeType === 3) {
8587
this._fragmentStart.data = this._fragmentEnd.data = ''
8688
}
87-
this._blockFragment = el
89+
this._fragment = el
8890
} else {
8991
this.$el = el
9092
}

src/transition/index.js

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -44,22 +44,6 @@ exports.remove = function (el, vm, cb) {
4444
}, vm, cb)
4545
}
4646

47-
/**
48-
* Remove by appending to another parent with transition.
49-
* This is only used in block operations.
50-
*
51-
* @param {Element} el
52-
* @param {Element} target
53-
* @param {Vue} vm
54-
* @param {Function} [cb]
55-
*/
56-
57-
exports.removeThenAppend = function (el, target, vm, cb) {
58-
apply(el, -1, function () {
59-
target.appendChild(el)
60-
}, vm, cb)
61-
}
62-
6347
/**
6448
* Apply transitions with an operation callback.
6549
*

src/util/dom.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,3 +309,21 @@ exports.findRef = function (node) {
309309
}
310310
}
311311
}
312+
313+
/**
314+
* Map a function to a range of nodes .
315+
*
316+
* @param {Node} node
317+
* @param {Node} end
318+
* @param {Function} op
319+
*/
320+
321+
exports.mapNodeRange = function (node, end, op) {
322+
var next
323+
while (node !== end) {
324+
next = node.nextSibling
325+
op(node)
326+
node = next
327+
}
328+
op(end)
329+
}

test/unit/specs/api/dom_spec.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ if (_.inBrowser) {
2020
parent.appendChild(sibling)
2121
var el = document.createElement('div')
2222
vm = new Vue({ el: el })
23-
// block instance
23+
// fragment instance
2424
var frag = document.createDocumentFragment()
2525
frag.appendChild(document.createElement('p'))
2626
frag.appendChild(document.createElement('span'))
@@ -38,7 +38,7 @@ if (_.inBrowser) {
3838
expect(spy.calls.count()).toBe(1)
3939
})
4040

41-
it('block instance', function () {
41+
it('fragment instance', function () {
4242
vm2.$appendTo(parent, spy)
4343
expect(parent.childNodes.length).toBe(6)
4444
expect(parent.childNodes[2]).toBe(vm2._fragmentStart)
@@ -64,7 +64,7 @@ if (_.inBrowser) {
6464
expect(spy.calls.count()).toBe(2)
6565
})
6666

67-
it('block instance', function () {
67+
it('fragment instance', function () {
6868
vm2.$prependTo(parent, spy)
6969
expect(parent.childNodes.length).toBe(6)
7070
expect(parent.childNodes[0]).toBe(vm2._fragmentStart)
@@ -95,7 +95,7 @@ if (_.inBrowser) {
9595
expect(spy.calls.count()).toBe(1)
9696
})
9797

98-
it('block instance', function () {
98+
it('fragment instance', function () {
9999
vm2.$before(sibling, spy)
100100
expect(parent.childNodes.length).toBe(6)
101101
expect(parent.childNodes[1]).toBe(vm2._fragmentStart)
@@ -124,7 +124,7 @@ if (_.inBrowser) {
124124
expect(spy.calls.count()).toBe(1)
125125
})
126126

127-
it('block instance', function () {
127+
it('fragment instance', function () {
128128
vm2.$after(target, spy)
129129
expect(parent.childNodes.length).toBe(6)
130130
expect(parent.childNodes[1]).toBe(vm2._fragmentStart)
@@ -135,7 +135,7 @@ if (_.inBrowser) {
135135
expect(spy.calls.count()).toBe(1)
136136
})
137137

138-
it('block instance no next sibling', function () {
138+
it('fragment instance no next sibling', function () {
139139
vm2.$after(sibling, spy)
140140
expect(parent.childNodes.length).toBe(6)
141141
expect(parent.childNodes[2]).toBe(vm2._fragmentStart)
@@ -161,7 +161,7 @@ if (_.inBrowser) {
161161
expect(spy.calls.count()).toBe(1)
162162
})
163163

164-
it('block instance', function () {
164+
it('fragment instance', function () {
165165
vm2.$before(sibling)
166166
expect(parent.childNodes.length).toBe(6)
167167
expect(parent.childNodes[1]).toBe(vm2._fragmentStart)

test/unit/specs/api/lifecycle_spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ if (_.inBrowser) {
9696
data: { test: 'frag' }
9797
})
9898
vm.$mount(frag)
99-
expect(vm._blockFragment).toBe(frag)
99+
expect(vm._fragment).toBe(frag)
100100
expect(vm.$el.nextSibling.textContent).toBe('frag')
101101
})
102102

test/unit/specs/transition/transition_spec.js

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,6 @@ if (_.inBrowser && !_.isIE9) {
7373
expect(spy).toHaveBeenCalled()
7474
})
7575

76-
it('removeThenAppend', function () {
77-
transition.removeThenAppend(target, el, vm, spy)
78-
expect(parent.childNodes.length).toBe(0)
79-
expect(el.firstChild).toBe(target)
80-
expect(spy).toHaveBeenCalled()
81-
})
82-
8376
})
8477

8578
describe('Skipping', function () {

0 commit comments

Comments
 (0)